SpringBoot-Shiro中使用缓存(2019.12.15)

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

在之前的权限控制中,每调用一次需要权限的Api时候,后台都会去数据库获取用户对应的权限,这对数据库来说是没必要的消耗。接下来使用缓存来解决这个问题。

使用Redis缓存解决

1. (引入依赖)

<!-- shiro-redis -->
<dependency>
    <groupId>org.crazycake</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>2.4.2.1-RELEASE</version>
</dependency>
<!-- 对象池,使用redis时必须引入 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

2. 配置Redis在application.yml配置文件中加入Redis配置

spring:
  redis:
    host: localhost
    port: 6379
    timeout: 0ms
    lettuce:
      pool:
      # 连接池最大连接数(使用负值表示没有限制) 默认 8
      max-active: 8
      # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
      max-wait: -1ms
      # 连接池中的最大空闲连接 默认 8
      max-idle: 8
      # 连接池中的最小空闲连接 默认 0
      min-idle: 0

3. 在ShiroConfig中配置Redis:

public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        //设置一小时超时  单位是秒
        redisManager.setExpire(3600);
        return redisManager;
    }
    
    /** 
     * 返回Redis缓存管理器 
     *
     * @return org.crazycake.shiro.RedisCacheManager 
     * @author: zhihao
     * @date: 2019/12/15 
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

//然后添加进web默认安全管理器
	@Bean
    public DefaultWebSecurityManager securityManager(){
        // 配置SecurityManager,并注入shiroRealm
      	...
        //设置管理器记住我
       	..
        //设置缓存管理器
        securityManager.setCacheManager(cacheManager());
        return securityManager;  
    }

4. 配置完毕启动项目进行测试

分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息:


Shiro使用redis记录session_缓存

启动项目如果出现 :ClassNotFoundException: org.apache.shiro.event.EventBus异常是因为Maven依赖的jar包中缺少了EventBus这个class文件,原来maven工程中已经依赖了shiro-core1.4.0的版本 ,在shiro-redis依赖中使用了shiro-core-1.2版本,把1.4版本的排除了出去, 而这个类要在1.3版本上才有,所以需要排除1.2版本

<!-- shiro-redis -->
    <dependency>
      <groupId>org.crazycake</groupId>
      <artifactId>shiro-redis</artifactId>
      <version>2.4.2.1-RELEASE</version>
      <exclusions>
        <exclusion>
          <artifactId>shiro-core</artifactId>
          <groupId>org.apache.shiro</groupId>
        </exclusion>
      </exclusions>
    </dependency>

使用Ehcache缓存解决

1.引入依赖

<!-- shiro ehcache -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- ehchache -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

2.Ehcache配置

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

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    updateCheck="false">
    <diskStore path="java.io.tmpdir/Tmp_EhCache" />
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120" />
    
    <!-- 登录记录缓存锁定1小时 -->
    <cache 
        name="passwordRetryCache"
        maxEntriesLocalHeap="2000"
        eternal="false"
        timeToIdleSeconds="3600"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        statistics="true" />
</ehcache>

3.ShiroConfig配置Ehcache

接着在ShiroConfig中注入Ehcache缓存:

@Bean
public EhCacheManager getEhCacheManager() {
    EhCacheManager cacheManager = new EhCacheManager();
    cacheManager.setCacheManagerConfigFile("classpath:config/shiro-ehcache.xml");
    return cacheManager;
}

//将缓存对象注入到SecurityManager中:
@Bean  
public SecurityManager securityManager(){  
    DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
    // 配置SecurityManager,并注入shiroRealm
      	...
        //设置管理器记住我
       	..
        //设置缓存管理器
    securityManager.setCacheManager(getEhCacheManager());
    return securityManager;  
}

4. 配置完毕启动项目进行测试

分别访问访问”获取用户信息”、”新增用户”和”删除用户”,可发现后台只打印一次获取权限信息: