SpringBoot 整合Shiro 集成Ehcache缓存

简介:用户访问资源时,每次都要进行权限认证,若去查询数据库,则会造成一定的压力。由于实际情况下,用户的权限一般不会发生改变,所以适合做缓存处理。单节点部署适合用ehcache缓存,若是分布式多节点部署,则应使用redis缓存

1. maven依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>

2. 设置缓存管理器,此处开启授权缓存,并加入securityManager中

/**
* 缓存管理器
*
* @return ehCacheManager
*/
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:shiro-ehcache.xml");

return ehCacheManager;
}

/**
* token认证和授权验证器
*
* @param ehCacheManager 缓存管理器
* @return jwtRealm
*/
@Bean
public JwtRealm jwtRealm(EhCacheManager ehCacheManager) {
JwtRealm jwtRealm = new JwtRealm();
jwtRealm.setCredentialsMatcher(new JwtCredentialsMatcher());
// 启用授权缓存
jwtRealm.setAuthorizationCachingEnabled(true);
jwtRealm.setAuthorizationCacheName("authorizationCache");
jwtRealm.setCacheManager(ehCacheManager);

return jwtRealm;
}

3. 配置shiro-ehcache.xml文件

  A. 参数配置详解

cache
name 缓存名称,通常为缓存对象的类名
maxEntriesLocalHeap 在本地内存中最大缓存项数量,0代表不限制
maxEntriesLocalDisk 磁盘中最大对象数,0代表不限制
eternal 设置为true,表示对象永远不会过期
timeToldleSeconds 对象处于空闲状态的最大时间,0代表不限制,只有当eternal为false时才有效
timeToliveSeconds 对象能够存活的最大时间,0代表不限制,只有当eternal为false时才有效
memoryStoreEvictionPolicy 内存回收策略(LRU、FIFO、LFU)
diskSpoolBufferSizeMB 磁盘缓存区的大小
 diskStore 配置磁盘存储的,可以存储内存中驱除过来的元素,又可以在系统重启的时候将内存中的缓存信息保存起来,供系统重新启动后使用

   B. 配置文件

<?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"
         monitoring="autodetect"
         dynamicConfig="true">

  <!-- 设置默认临时文件路径 --> <diskStore path="java.io.tmpdir"/>
<cache name="authorizationCache"
maxEntriesLocalHeap="1000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="7200"
timeToLiveSeconds="28800"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
</cache>
</ehcache>

4. 若用户的权限发生改变,该如何处理

  A. 在jwtRelam中加入缓存清理方法

 

  B. 在改变权限(修改角色中权限或者删除角色)的代码下,加入如下代码

/**
* 清除权限缓存
*/
private void clearCache() {
DefaultWebSecurityManager webSecurityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
ModularRealmAuthorizer authorizer = (ModularRealmAuthorizer) webSecurityManager.getAuthorizer();
JwtRealm realm = (JwtRealm) authorizer.getRealms().iterator().next();
realm.clearCachedAuthorizationInfo();
}

  5. 引用缓存时出现的错误

    错误一:使用ehcache缓存后,程序启动报错,主要是缓存文件重名引起的

     原因:这是由于自定义的缓存文件名与shiro自带的缓存文件名classpath:org/apache/shiro/cache/ehcache/ehcache.xml重复

     解决:修改文件名,如换为ehcache-shiro.xml即可

/**
* 缓存管理器
*
* @return ehCacheManager
*/
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");

return ehCacheManager;
}

  错误二:缓存不生效,主要是cacheManager为null引起的

   原因:多realm下,在SecurityManager下设置cacheManager不生效,即:securityManager.setCacheManager(cacheManager)

   解决:需要在指定的realm中设置cacheManager,如:

/**
* token认证和授权验证器
*
* @param ehCacheManager 缓存管理器
* @return jwtRealm
*/
@Bean
public JwtRealm jwtRealm(EhCacheManager ehCacheManager) {
JwtRealm jwtRealm = new JwtRealm();
jwtRealm.setCredentialsMatcher(new JwtCredentialsMatcher());
// 启用授权缓存,注意cacheManager应写在后面
jwtRealm.setAuthorizationCachingEnabled(true);
jwtRealm.setAuthorizationCacheName("authorizationCache");
jwtRealm.setCacheManager(ehCacheManager);

return jwtRealm;
}
  错误三:使用ehcache缓存后,程序启动报错,主要是代码顺序引起的

   原因:自定义realm中设置cacheManager时,若后设置缓存名,则无效,因为AuthenticatingRealm类中会默认设置个缓存名,这样导致在缓存文件中找不到该名

   解决:应如错误二中解决写的代码

 

可参考:ehcache2.x配置文件详解

posted @ 2020-01-02 08:32  如幻行云  阅读(4071)  评论(0编辑  收藏  举报