8.权限控制性能提升
8.1.自定义Shiro Filter过滤器
(1)shiro默认的roles过滤器存在的问题
(2)自定义过滤器类,继承AuthorizationFilter
public class CustomRolesAuthorizationFilter extends AuthorizationFilter { @Override public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { Subject subject = getSubject(request, response); String[] rolesArray = (String[]) mappedValue; if (rolesArray == null || rolesArray.length == 0) { //no roles specified, so nothing to check - allow access. return true; } Set<String> roles = CollectionUtils.asSet(rolesArray); //filterChainDefinitionMap.put("/admin/**","roles[admin,root]") // shiro配置角色默认是与的关系,需要都满足,这里改成或的关系,只要有其中一个即可 for (String role : roles) { if (subject.hasRole(role)){ return true; } } return false; } }
(3)ShiroConfig中配置自定义过滤器
//设置自定义过滤器 Map<String, Filter> filterMap = new HashMap<>(); filterMap.put("customRolesFilter",new CustomRolesAuthorizationFilter()); shiroFilterFactoryBean.setFilters(filterMap);
8.2.Redis整合CacheManager
- Redis整合CacheManager为了提高性能,避免每次都去库查
(1)加入shiro-redis依赖(shiro和redis整合的jar包)
<!--shiro整合redis--> <dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis</artifactId> <version>3.1.0</version> </dependency>
(2)ShiroConfig中配置,RedisManager,RedisCacheManager,SecruityManager
/** * 加入RedisManager */ public RedisManager getRedisManager(){ RedisManager redisManager = new RedisManager(); redisManager.setHost("192.168.10.88"); redisManager.setPort(6379); return redisManager; } /** * 配置RedisCacheManager */ public RedisCacheManager cacheManager(){ RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(getRedisManager()); //设置过期时间,单位秒 redisCacheManager.setExpire(60); return redisCacheManager; }
(3)改造现有逻辑自定义的Realm
doGetAuthorizationInfo 方法 原有: String username = (String)principals.getPrimaryPrincipal(); User user = userService.findAllUserInfoByUsername(username); 改为 User newUser = (User)principals.getPrimaryPrincipal(); User user = userService.findAllUserInfoByUsername(newUser.getUsername()); doGetAuthenticationInfo方法 原有: return new SimpleAuthenticationInfo(username, user.getPassword(), this.getClass().getName()); 改为 return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
8.3.Redis整合SessionManager
(1)加入SessionDAO的配置
/** * 配置SessionDAO */ public RedisSessionDAO sessionDAO(){ RedisSessionDAO sessionDAO = new RedisSessionDAO(); //设置RedisManager sessionDAO.setRedisManager(getRedisManager()); return sessionDAO; }
(2)自定义的sessionManager中设置sessionDAO
//设置Session持久化,RedisSessionManager //注意:如果不设置过期时间,redis中存储也和shiro中session的默认过期时间保持一致 customSessionManager.setSessionDAO(sessionDAO());
(3)注意传输的实体类都要实现Serializable接口,否则会报错
8.4.ShiroConfig常用的Bean配置
(1)LifecycleBeanPostProcessor:管理shiro一些bean的生命周期,即bean初始化与销毁
@Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); }
(2)AuthorizationAttributeSourceAdvisor:加入注解的使用,不加入这个AOP注解不生效(@RequiresGuest)
@Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; }
(3)DefaultAdvisorAutoProxyCreator:用来扫描上下文寻找的所有Advistor(通知器),将符合条件的Advisor应用到切入点的Bean中,需要在LifecycleBeanPostProcessor创建后才可以创建
@Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setUsePrefix(true); return defaultAdvisorAutoProxyCreator; }
9.分布式应用鉴权方式
9.1.自定义SessionId
- Shiro 默认的sessionid生成 类名 SessionIdGenerator
- 创建CustomSessionIdGenerator类,实现 SessionIdGenerator 接口的方法
/** * 自定义session持久化 * @return */ public RedisSessionDAO redisSessionDAO(){ RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(getRedisManager()); //设置sessionid生成器 redisSessionDAO.setSessionIdGenerator(new CustomSessionIdGenerator()); //设置自定义的sessionIdGenerator return redisSessionDAO; }