一、前言
在Shiro中加入缓存可以使权限相关操作尽可能快,避免频繁访问数据库获取权限信息,因为对于一个用户来说,其权限在短时间内基本是不会变化的。Shiro提供了Cache的抽象,其并没有直接提供相应的实现,因为这已经超出了一个安全框架的范围。在Shiro中可以集成常用的缓存实现,这里介绍基于Redis和Ehcache缓存的实现。
在《Spring-Boot-shiro权限控制》中,当用户访问”获取用户信息”、”新增用户”和”删除用户”的时候,后台输出了三次打印信息,如下所示:
用户wno704获取权限-----ShiroRealm.doGetAuthorizationInfo
用户wno704获取权限-----ShiroRealm.doGetAuthorizationInfo
用户wno704获取权限-----ShiroRealm.doGetAuthorizationInfo
说明在这三次访问中,Shiro都会从数据库中获取用户的权限信息,通过Druid数据源SQL监控后台也可以证实这一点:
这对数据库来说是没必要的消耗。接下来使用缓存来解决这个问题。
二、Redis缓存
2.1 引入Redis依赖
网络上已经有关于Shiro集成Redis的实现,我们引入即可:
<!-- https://mvnrepository.com/artifact/org.crazycake/shiro-redis --><dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>3.3.1</version></dependency>2.2 配置Redis
我们在application.yml配置文件中加入Redis配置:
spring:redis:host:127.0.0.1port:10007password:jedis:pool:max-active:8max-wait:-1max-idle:8min-idle:0timeout:02.3 配置Redis
接着在ShiroConfig中配置Redis:
@Value("${spring.redis.host}")privateStringredisHost;@Value("${spring.redis.port}")privateStringredisPost;@Value("${spring.redis.timeout}")privateintredisTimeout;@Value("${spring.redis.password}")privateStringredisPassword;publicRedisManagerredisManager(){RedisManagerredisManager=newRedisManager();redisManager.setHost(redisHost+":"+redisPost);redisManager.setTimeout(redisTimeout);if(!(redisPassword==null||redisPassword.equals(""))){redisManager.setPassword(redisPassword);}returnredisManager;}publicRedisCacheManagercacheManager(){RedisCacheManagerredisCacheManager=newRedisCacheManager();redisCacheManager.setRedisManager(redisManager());returnredisCacheManager;}2.4 注入RedisManager
上面代码配置了RedisManager,并将其注入到了RedisCacheManager中,最后在SecurityManager中加入RedisCacheManager:
@BeanpublicSecurityManagersecurityManager(){DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager();...securityManager.setCacheManager(cacheManager());returnsecurityManager;}2.5 测试
配置完毕启动项目,分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息:
用户wno704获取权限-----ShiroRealm.doGetAuthorizationInfo
查看Druid数据源SQL监控:
三、Ehcache
3.1 Ehcache依赖
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.6.0</version></dependency>3.2 Ehcache配置
在src/main/resource/config路径下新增一个Ehcache配置——shiro-ehcache.xml:
<?xml version="1.0" encoding="UTF-8"?><ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"updateCheck="false"><diskStorepath="java.io.tmpdir/Tmp_EhCache"/><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!-- 登录记录缓存锁定1小时 --><cachename="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"/></ehcache>3.3 ShiroConfig配置Ehcache
接着在ShiroConfig中注入Ehcache缓存:
@BeanpublicEhCacheManagergetEhCacheManager(){EhCacheManagerem=newEhCacheManager();em.setCacheManagerConfigFile("classpath:config/shiro-ehcache.xml");returnem;}3.4 注入EhCacheManager
将缓存对象注入到SecurityManager中:
@BeanpublicSecurityManagersecurityManager(){DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager();securityManager.setRealm(shiroRealm());securityManager.setRememberMeManager(rememberMeManager());securityManager.setCacheManager(getEhCacheManager());returnsecurityManager;}3.5 测试
配置完毕启动项目,分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息:
用户wno704获取权限-----ShiroRealm.doGetAuthorizationInfo
查看Druid数据源SQL监控:
SQL只执行了一次,说明缓存成功。