历史文章
(一)Spring Boot 集成 Shiro 权限管理与密码加盐
主要完成功能
权限信息缓存功能:不用每次请求都去请求数据库
没有加缓存的情况下
用户登录成功或,获取添加了权限注解的接口时会调用 MyRealm.doGetAuthorizationInfo 方法,每请求一次就会查询一次数据库,这样是相当浪费性能的。
配置SecurityManager 的 CacheManager
添加 pom 文件
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.2.2</version>
</dependency>
修改 ShiroConfig.java 添加 CacheManager
/**
* 添加缓存
* @return
*/
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost("127.0.0.1:6379");
redisManager.setPassword("foobared");
return redisManager;
}
/**
* 添加缓存
* @return
*/
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
@Bean
SecurityManager securityManager() {
DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
defaultSecurityManager.setRealm(myRealm());
defaultSecurityManager.setRememberMeManager(rememberMeManager());
//添加 shiro 缓存管理
defaultSecurityManager.setCacheManager(cacheManager());
return defaultSecurityManager;
}
修改 MyRealm
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
System.out.println("获取权限");//添加日志查看请求次数
User user = (User) principal.getPrimaryPrincipal();
String userName = user.getName();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
roleMapper.selectListByUserName(userName).forEach(
role -> {
authorizationInfo.addRole((String) role.get("name"));
permissionMapper.selectListByRoleId((Long) role.get("id")).forEach(
permission -> authorizationInfo.addStringPermission((String) permission.get("name"))
);
}
);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
User user = userMapper.selectByName(username);
if (user == null) {
throw new UnknownAccountException("用户不存在");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user, //修改为传入对象,该对象需要有属性 id 并提供 getter/setter 方法
user.getPassword(),
ByteSource.Util.bytes(user.getSalt()),
getName()
);
return authenticationInfo;
}
测试
在未配置前,请求一次权限相关接口就会调用一次 MyRealm.doGetAuthorizationInfo() 方法
配置后,请求时只有登录成功后的第一次会请求 MyRealm.doGetAuthorizationInfo() 方法,之后请求不会调用 MyRealm.doGetAuthorizationInfo() 方法。退出登录后重新登录后请求权限相关接口又会请求一次 MyRealm.doGetAuthorizationInfo() 。