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 |
|
||||||||||||||||
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配置文件详解