https://blog.csdn.net/sco5282/article/details/134016549
前面已经学习了Shiro快速入门和缓存 。现在假定实际业务中需要完成以下功能:
1. 包含页面登录和首页。
2. 登录时需要连接数据库,完成登录认证和授权。
3. 登录时,密码需要加密。
4. 登录和授权信息能够缓存。
5. 授权演示两种模式,基于角色授权和基于资源授权。
前提条件
因为这里主要学习shiro,所以与shiro不相干的步骤和准备,尽量简单表示。
1. 新建SpringBoot的Web项目,并新建页面index.html(主页,对应路由ip:接口/index)和login.html(登录页面,对应路由ip:接口/login)。
2. mysql数据库包含用户、角色以及授权的表格(如下图)。这些表格的方法已在SpringBoot结合(Mybatis或Mybatisplus)形成基础的查询方法,我们演示的时候只要调用以上方法即可。
引入依赖
这里我们需要引用需要的shiro和redis依赖项。
1 <dependency> 2 <groupId>org.apache.shiro</groupId> 3 <artifactId>shiro-spring</artifactId> 4 <version>1.13.0</version> 5 </dependency> 6 <!-- Redis 缓存--> 7 <dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-data-redis</artifactId> 10 <version>2.5.15</version> 11 </dependency> 12 <dependency> 13 <groupId>org.springframework.data</groupId> 14 <artifactId>spring-data-redis</artifactId> 15 <version>2.5.12</version> 16 </dependency>
添加Shiro配置类
根据已学过的知识,添加配置类ShiroConfiguratin。
1 @Configuration 2 public class ShiroConfiguratin { 3 @Autowired 4 private RedisTemplate redisTemplate; 5 6 // 1.创建 shiroFilter,负责拦截所有请求 7 @Bean 8 public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ 9 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 10 //给filter设置安全管理器 11 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); 12 //配置系统受限资源 13 //配置系统公共资源 14 Map<String,String> map = new HashMap<>(); 15 // authc 请求这个资源需要认证和授权 16 map.put("/index", "authc"); 17 //默认认证界面路径 18 shiroFilterFactoryBean.setLoginUrl("/login"); 19 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); 20 return shiroFilterFactoryBean; 21 } 22 23 //2.创建安全管理器 24 @Bean 25 public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){ 26 DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); 27 //给安全管理器设置 28 defaultWebSecurityManager.setRealm(realm); 29 return defaultWebSecurityManager; 30 } 31 32 /** 33 * 3.创建自定义realm 34 * @return 35 */ 36 @Bean 37 public Realm getRealm(){ 38 SysUserRealm sysUserRealm = new SysUserRealm(); 39 // 设置缓存管理器 40 sysUserRealm.setCacheManager(new RedisCacheManage(redisTemplate)); // 自定义Redis数据库缓存方法 41 // 开启全局缓存 42 sysUserRealm.setCachingEnabled(true); 43 // 开启认证缓存并指定缓存名称 44 sysUserRealm.setAuthenticationCachingEnabled(true); 45 sysUserRealm.setAuthenticationCacheName("authenicationCache"); 46 // 开启缓存授权并指定缓存名称 47 sysUserRealm.setAuthorizationCachingEnabled(true); 48 sysUserRealm.setAuthorizationCacheName("authenicationCache"); 49 return sysUserRealm; 50 } 51 }
这里的配置类完成以下功能。
- 完成拦截请求(登录index页面前,需要经过认证和授权认证和授权页面(login))
- 创建安全管理(添加域管理器)
- 设置自定义域,完成缓存的设置(使用Redis缓存,详见:https://www.cnblogs.com/luyj00436/p/18446712)。
根据之前学到的知识,自定义域完成了认证和授权 SysUserRealm 。
1 public class SysUserRealm extends AuthorizingRealm { 2 @Autowired 3 private SysUserMapper sysUserMapper; // 用户查询 4 /** 5 * 授权 6 * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved. 7 * @return 8 */ 9 @Override 10 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 11 // 从系统返回的身份信息集合中获取主身份信息(用户名) 12 String primaryPrincipal = (String) principals.getPrimaryPrincipal(); 13 // TODO 根据用户名获取当前用户的角色信息,以及权限信息 14 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 15 // 将数据库中查询到的角色信息赋值给权限对象 16 simpleAuthorizationInfo.addRole("admin"); 17 simpleAuthorizationInfo.addRole("user"); 18 // 将数据库中查询权限信息赋值给权限对象 19 simpleAuthorizationInfo.addStringPermission("user:*:01"); 20 simpleAuthorizationInfo.addStringPermission("product:create"); 21 return simpleAuthorizationInfo; 22 } 23 24 /** 25 * 认证 26 * @param token the authentication token containing the user's principal and credentials. 27 * @return 28 * @throws AuthenticationException 29 */ 30 @Override 31 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 32 // 在token中获取用户名 33 String principal = (String) token.getPrincipal(); // 获取用户名 34 // 根据获取到的用户名查询数据(这里用id代替) 35 SysUser resUser = sysUserMapper.selectById(1); 36 if(principal.equals(resUser.getUsername())){ 37 // 参数说明:用户|密码|当前realm的名字 38 return new SimpleAuthenticationInfo(principal,resUser.getPassword(), this.getName() ); 39 } 40 return null; 41 } 42 }