在Shiro中加入缓存可以使权限相关操作尽可能快,避免频繁访问数据库获取权限信息,因为对于一个用户来说,其权限在短时间内基本是不会变化的。Shiro提供了Cache的抽象,其并没有直接提供相应的实现,因为这已经超出了一个安全框架的范围。在Shiro中可以集成常用的缓存实现,这里介绍基于Redis和Ehcache缓存的实现。

《Spring-Boot-shiro权限控制》中,当用户访问”获取用户信息”、”新增用户”和”删除用户”的时候,后台输出了三次打印信息,如下所示:

  1. 用户mrbird获取权限-----ShiroRealm.doGetAuthorizationInfo
  2. 用户mrbird获取权限-----ShiroRealm.doGetAuthorizationInfo
  3. 用户mrbird获取权限-----ShiroRealm.doGetAuthorizationInfo

说明在这三次访问中,Shiro都会从数据库中获取用户的权限信息,通过Druid数据源SQL监控后台也可以证实这一点:

Spring Boot Shiro中使用缓存 - 图1

这对数据库来说是没必要的消耗。接下来使用缓存来解决这个问题。

Redis

引入Redis依赖

网络上已经有关于Shiro集成Redis的实现,我们引入即可:

  1. <!-- shiro-redis -->
  2. <dependency>
  3. <groupId>org.crazycake</groupId>
  4. <artifactId>shiro-redis</artifactId>
  5. <version>3.3.1</version>
  6. </dependency>

配置Redis

我们在application.yml配置文件中加入Redis配置:

  1. spring:
  2. redis:
  3. host: localhost
  4. port: 6379
  5. pool:
  6. max-active: 8
  7. max-wait: -1
  8. max-idle: 8
  9. min-idle: 0
  10. timeout: 10000

接着在ShiroConfig中配置Redis:

  1. public RedisManager redisManager() {
  2. RedisManager redisManager = new RedisManager();
  3. return redisManager;
  4. }
  5. public RedisCacheManager cacheManager() {
  6. RedisCacheManager redisCacheManager = new RedisCacheManager();
  7. redisCacheManager.setRedisManager(redisManager());
  8. return redisCacheManager;
  9. }

上面代码配置了RedisManager,并将其注入到了RedisCacheManager中,最后在SecurityManager中加入RedisCacheManager:

  1. @Bean
  2. public SecurityManager securityManager(){
  3. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  4. ...
  5. securityManager.setCacheManager(cacheManager());
  6. return securityManager;
  7. }

配置完毕启动项目,分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息:

  1. 用户mrbird获取权限-----ShiroRealm.doGetAuthorizationInfo

查看Druid数据源SQL监控:http://localhost:8080/web/druid/login.html

Spring Boot Shiro中使用缓存 - 图2

Ehcache

Ehcache依赖

加入Ehcache相关依赖:

  1. <!-- shiro ehcache -->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-ehcache</artifactId>
  5. <version>1.3.2</version>
  6. </dependency>
  7. <!-- ehchache -->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-cache</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>net.sf.ehcache</groupId>
  14. <artifactId>ehcache</artifactId>
  15. </dependency>

Ehcache配置

在src/main/resource/config路径下新增一个Ehcache配置——shiro-ehcache.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
  4. updateCheck="false">
  5. <diskStore path="java.io.tmpdir/Tmp_EhCache" />
  6. <defaultCache
  7. maxElementsInMemory="10000"
  8. eternal="false"
  9. timeToIdleSeconds="120"
  10. timeToLiveSeconds="120"
  11. overflowToDisk="false"
  12. diskPersistent="false"
  13. diskExpiryThreadIntervalSeconds="120" />
  14. <!-- 登录记录缓存锁定1小时 -->
  15. <cache
  16. name="passwordRetryCache"
  17. maxEntriesLocalHeap="2000"
  18. eternal="false"
  19. timeToIdleSeconds="3600"
  20. timeToLiveSeconds="0"
  21. overflowToDisk="false"
  22. statistics="true" />
  23. </ehcache>

ShiroConfig配置Ehcache

接着在ShiroConfig中注入Ehcache缓存:

  1. @Bean
  2. public EhCacheManager getEhCacheManager() {
  3. EhCacheManager em = new EhCacheManager();
  4. em.setCacheManagerConfigFile("classpath:config/shiro-ehcache.xml");
  5. return em;
  6. }

将缓存对象注入到SecurityManager中:

  1. @Bean
  2. public SecurityManager securityManager(){
  3. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  4. securityManager.setRealm(shiroRealm());
  5. securityManager.setRememberMeManager(rememberMeManager());
  6. securityManager.setCacheManager(getEhCacheManager());
  7. return securityManager;
  8. }

配置完毕启动项目,分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息:

  1. 用户mrbird获取权限-----ShiroRealm.doGetAuthorizationInfo

查看Druid数据源SQL监控:

Spring Boot Shiro中使用缓存 - 图3

SQL只执行了一次,说明缓存成功。