3.Springboot集成Shiro
(1).创建环境
1.在刚刚的父项目中新建一个 springboot 模块
2.导入Thymeleaf驱动器依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.7.7</version> </dependency>
3.在Template的包中创建首页并且利用Thymeleaf进行取值的操作
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>首页</h1> <p th:text="${msg}"></p> </body> </html>
4.创建Controller测试是否成功
package com.jsxs.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MyController { @RequestMapping({"/","/index.html","index"}) public String index(Model model){ model.addAttribute("msg","Hello,Shiro"); System.out.println("第一步----》跳转index页面成功!!!"); return "index"; } }
5.导入 SpringBoot 和 Shiro 整合包的依赖
<!--SpringBoot 和 Shiro 整合包--> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-web-starter --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.6.0</version> </dependency
下面是编写配置文件
Shiro 三大要素
subject -> ShiroFilterFactoryBean ----当前用户
securityManager -> DefaultWebSecurityManager ----管理所有用户
Realm
实际操作中对象创建的顺序 : realm -> securityManager -> subject ----连接数据
6.创建config文件,编写UserRealm.java继承AuthorizingRealm并实现方法
package com.jsxs.config; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class UserRealm extends AuthorizingRealm { // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=》授权的方法"); return null; } // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=》认证的方法"); return null; } }
可以两个方法的功能主要实现了授权和认证,我们添加两个输出一会看看效果
7.在Config文件夹下编写ShiroConfig.java文件,将三大Bean注入到spring中
①根据前面提供的顺序,先编写realm类:
//创建 Realm 对象 ----》 Realm 需要自定义----> 01 @Bean(name = "userRealm") public UserRealm userRealm(){ return new UserRealm(); }
②创建用户管理,这里需要用到前面创建的realm,因此在realm之后进行编写
//DefaultWebSecurityManger ----》 SecurityManger ---->02 @Bean(name = "getDefaultWebSecurityManager") // 设置这个Bean的name 默认的是---》方法名 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm Realm){ // 通过注解指定是 public UserRealm userRealm() 这个Bean DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(Realm); //进行关联 Realm return defaultWebSecurityManager; }
③创建subject,需要传入一个securityManager,因此最后进行编写(是不是很像套娃)
// ShiroFilterFactoryBean ----》 Subject @Bean(name = "shiroFilterFactoryBean") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ // 通过注解指定是 public DefaultWebSecurityManager getDefaultWebSecurityManager 这个Bean ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //设置安全管理器 return shiroFilterFactoryBean; }
package com.jsxs.config; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { // ShiroFilterFactoryBean ----》 Subject @Bean(name = "shiroFilterFactoryBean") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ // 通过注解指定是 public DefaultWebSecurityManager getDefaultWebSecurityManager 这个Bean ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //设置安全管理器 /** * anno :无需认证就可以访问 * authc : 必须认证了才能访问 * user :必须拥有 记住我 功能才有用 * perms : 拥有对某个资源的权限才能访问 * role : 拥有某个角色权限次啊能使用 */ Map<String, String> filterMap = new LinkedHashMap<>();// filterMap.put("/add","authc"); filterMap.put("/add.html","authc"); filterMap.put("/update","authc"); filterMap.put("/update.html","authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); //这个一定要添加 //设置登入的请求 shiroFilterFactoryBean.setLoginUrl("/toLogin"); return shiroFilterFactoryBean; } //DefaultWebSecurityManger ----》 SecurityManger ---->02 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ // 通过注解指定是 public UserRealm userRealm() 这个Bean DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(userRealm); //进行关联 Realm return defaultWebSecurityManager; } //创建 Realm 对象 ----》 Realm 需要自定义----> 01 @Bean(name = "userRealm") public UserRealm userRealm(){ return new UserRealm(); } }
8.设置路由映射的信息
package com.jsxs.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping({"/","jsxs"}) public class MyController { // 首页 @RequestMapping({"/","/index.html","index"}) public String index(Model model){ model.addAttribute("msg","Hello,Shiro"); System.out.println("第一步----》跳转index页面成功!!!"); return "index"; } // 添加 @RequestMapping({"/add.html","/add"}) public String add(){ return "user/add"; } // 修改 @RequestMapping({"/update.html","/update"}) public String update(){ return "user/update"; } }
9.设置跳转路径
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>首页</h1> <p th:text="${msg}"></p> <hr> <a th:href="@{/add}">add</a> | <a th:href="@{/update}">update</a> </body> </html>
以上的链接无需认证就可以直接访问了
(2).实现登入拦截
/** * anno :无需认证就可以访问 * authc : 必须认证了才能访问 * user :必须拥有 记住我 功能才有用 * perms : 拥有对某个资源的权限才能访问 * role : 拥有某个角色权限次啊能使用 */
// ShiroFilterFactoryBean ----》 Subject @Bean(name = "shiroFilterFactoryBean") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ // 通过注解指定是 public DefaultWebSecurityManager getDefaultWebSecurityManager 这个Bean ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //设置安全管理器 /** * anno :无需认证就可以访问 * authc : 必须认证了才能访问 * user :必须拥有 记住我 功能才有用 * perms : 拥有对某个资源的权限才能访问 * role : 拥有某个角色权限次啊能使用 */ Map<String, String> filterMap = new LinkedHashMap<>();// filterMap.put("/add","authc"); filterMap.put("/add.html","authc"); filterMap.put("/update","authc"); filterMap.put("/update.html","authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); //这个一定要添加 //设置登入的请求 shiroFilterFactoryBean.setLoginUrl("/toLogin"); return shiroFilterFactoryBean;
图示解析:
当然在拦截请求中也支持通配符:如拦截指定/user下的所有请求:/user/*
(3).实现用户认证
实现用户认证需要去realm类的认证方法中去配置
这里我们先把用户名和密码写死,实际中是要去数据库中去取的
去到UserRealm.java中
package com.jsxs.config; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; public class UserRealm extends AuthorizingRealm { // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=》授权的方法"); return null; } // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了=》认证的方法"); String name = "admin"; String password = "123456"; UsernamePasswordToken userToken = (UsernamePasswordToken) token; if (!userToken.getUsername().equals(name)) { return null; // 抛出异常 Unknow } // 密码认证 ----》Shiro帮我们做 return new SimpleAuthenticationInfo("",password,""); } }