Shiro的缓存是被Shiro的缓存管理器所管理的,即CacheManage,Shiro的用户认证是默认是不开启身份验证缓存,即不缓存AuthenticationInfo info信息,用户登陆正常只进行一次,用户认证是可以不设置缓存。
shiro的授权缓存是默是开启的,主要因为授权的数据量大。下文对认证、授权均开启缓存。
本文在上一篇文章 Shiro功能应用(二)–记住我功能实现代码基础进行添加EHCache缓存。
代码实现:
代码地址:
https://github.com/OooooOz/SpringBoot-Shiro
前台页面、成功跳转页面代码都不变
ShiroConfig的安全管理器SecurityManager:
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("shiroRealm") MyShiroRealm shiroRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm);
securityManager.setRememberMeManager(rememberMeManager()); //实现记住我
securityManager.setCacheManager(getEhCacheManager()); //实现缓存
return securityManager;
}
ShiroConfig的新增缓存配置:
@Bean
public EhCacheManager getEhCacheManager(){
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:cache/ehcache-shiro.xml");
return cacheManager;
}
缓存配置文件ehcache-shiro.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
<!-- 授权缓存 -->
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="60" //缓存60s后失效
overflowToDisk="false"
statistics="true">
</cache>
<!-- 认证缓存 -->
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="60" //缓存60s后失效
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>
自定义Realm开启缓存:
@Bean(name="shiroRealm")
public MyShiroRealm getMyShiroRealm(@Qualifier("credentialsMatcher")HashedCredentialsMatcher credentialsMatcher){
MyShiroRealm shiroRealm = new MyShiroRealm();
shiroRealm.setCredentialsMatcher(credentialsMatcher);//设置密码比较器
shiroRealm.setCachingEnabled(true);
//启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
shiroRealm.setAuthenticationCachingEnabled(true);
//缓存AuthenticationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置
shiroRealm.setAuthenticationCacheName("authenticationCache");
//启用授权缓存,即缓存AuthorizationInfo信息,默认true
// shiroRealm.setAuthorizationCachingEnabled(true);
//缓存AuthorizationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置
shiroRealm.setAuthorizationCacheName("authorizationCache");
return shiroRealm;
}
控制器添加权限方法:
@RequestMapping("/toAdd.do")
public String addFunction(Model model){
User user = (User) SecurityUtils.getSubject().getPrincipal();
//添加权限
//打断点,利用断点时间直接修改数据库,懒得写代码
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager)SecurityUtils.getSecurityManager();
MyShiroRealm shiroRealm = (MyShiroRealm) securityManager.getRealms().iterator().next();
//清除当前登录者的认证缓存
shiroRealm.getAuthenticationCache().remove(user.getUserName());
//清除当前登录者的授权缓存
shiroRealm.getAuthorizationCache().remove(SecurityUtils.getSubject().getPrincipals());
List<User> list = userService.findAll();
model.addAttribute("userList", list);
return "userList";
}
功能测试:
访问http://localhost:8080/userList.do,跳转登陆页面,登陆成功后,关闭浏览器再次访问,然后登陆,看控制台输出,只输出一次“执行了认证方法”,过了60s后再次访问登陆,此时缓存失效时间到了,就再一次输出“执行了认证方法”
过程:
第一次登陆,缓存中无info信息,便执行doGetAuthenticationInfo,跳转到自定义Realm的认证方法获取Info,所以输出了“执行了认证方法”
第二次登陆时,直接从缓存中获取info,所以不走自定义Realm的认证方法,故不输出“执行了认证方法”
第三次登陆时,缓存失效时间已经到了,从缓存中获取不到info,所以会跳转到自定义Realm的认证方法获取,所以又输出了“执行了认证方法”。
授权缓存也一样, 访问http://localhost:8080/userList.do,跳转登陆页面,登陆成功调整成功页面,页面有三个shiro:hasPermission标签,所以会访问三次Shiro内部授权方法。
第一次访问,缓存中没有AuthorizationInfo info信息,执行doGetAuthorizationInfo跳转到自定义Realm的授权方法中获取,之后将获取的对象put进缓存,所以第一个shiro:hasPermission标签后台会打印"执行了授权的方法"
第二、三次访问,都能从缓存中获取AuthorizationInfo info对象,所以不会访问自定义Realm的授权方法
当60s后,缓存失效了,再次登陆,又重复上次过程,只输出一次"执行了授权的方法"。
消除缓存:
当用户更改密码,或变更权限,如果不更新缓存,用户无法登陆或者无法拥有新的权限功能。所以用户信息做变更后,要清除掉该用户的缓存,这样下次登陆就可以刷新缓存了。消除当前用户缓存的方法:
//清除当前登录者的认证缓存
shiroRealm.getAuthenticationCache().remove(user.getUserName());
//清除当前登录者的授权缓存
shiroRealm.getAuthorizationCache().remove(SecurityUtils.getSubject().getPrincipals());
测试过程:
登陆成功后,点击添加,会跳转到控制器,进行消除缓存操作。之后再次登陆,可以看见控制台输出“执行了认证方法”、“执行了授权的方法”