Shiro 缓存机制

JAVA herman 2563浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

缓存,我的理解是:让数据更接近于使用者;工作机制是:先从缓存中读取数据,如果没有再从慢速设备上读取实际数据(数据也会存入缓存);缓存什么:那些经常读取且不经常修改的数据/那些昂贵(CPU/IO)的且对于相同的请求有相同的计算结果的数据。如CPU–L1/L2–内存–磁盘就是一个典型的例子,CPU需要数据时先从L1/L2中读取,如果没有到内存中找,如果还没有会到磁盘上找。还有如用过Maven的朋友都应该知道,我们找依赖的时候,先从本机仓库找,再从本地服务器仓库找,最后到远程仓库服务器找;还有如京东的物流为什么那么快?他们在各个地都有分仓库,如果该仓库有货物那么送货的速度是非常快的。

Shiro提供了类似于Spring的Cache抽象,即Shiro本身不实现Cache,但是对Cache进行了又抽象,方便更换不同的底层Cache实现。

Shiro提供的Cache接口

public interface Cache<K, V> {  
    //根据Key获取缓存中的值  
    public V get(K key) throws CacheException;  
    //往缓存中放入key-value,返回缓存中之前的值  
    public V put(K key, V value) throws CacheException;   
    //移除缓存中key对应的值,返回该值  
    public V remove(K key) throws CacheException;  
    //清空整个缓存  
    public void clear() throws CacheException;  
    //返回缓存大小  
    public int size();  
    //获取缓存中所有的key  
    public Set<K> keys();  
    //获取缓存中所有的value  
    public Collection<V> values();  
}

Shiro提供的CacheManager接口

public interface CacheManager {  
    //根据缓存名字获取一个Cache  
    public <K, V> Cache<K, V> getCache(String name) throws CacheException;  
} 

Shiro还提供了CacheManagerAware用于注入CacheManager

public interface CacheManagerAware {  
    //注入CacheManager  
    void setCacheManager(CacheManager cacheManager);  
}  

Shiro内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如Realm)是否实现了CacheManagerAware并自动注入相应的CacheManager。

Realm缓存

Shiro提供了CachingRealm,其实现了CacheManagerAware接口,提供了缓存的一些基础实现;另外AuthenticatingRealm及AuthorizingRealm分别提供了对AuthenticationInfo 和AuthorizationInfo信息的缓存。ini配置 代码如下:

userRealm=com.xttblog.shiro10.realm.UserRealm  
userRealm.credentialsMatcher=$credentialsMatcher  
userRealm.cachingEnabled=true  
userRealm.authenticationCachingEnabled=true  
userRealm.authenticationCacheName=authenticationCache  
userRealm.authorizationCachingEnabled=true  
userRealm.authorizationCacheName=authorizationCache  
securityManager.realms=$userRealm  
  
cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager  
cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml  
securityManager.cacheManager=$cacheManager  
  • userRealm.cachingEnabled:启用缓存,默认false;
  • userRealm.authenticationCachingEnabled:启用身份验证缓存,即缓存AuthenticationInfo信息,默认false;
  • userRealm.authenticationCacheName:缓存AuthenticationInfo信息的缓存名称;
  • userRealm. authorizationCachingEnabled:启用授权缓存,即缓存AuthorizationInfo信息,默认false;
  • userRealm. authorizationCacheName:缓存AuthorizationInfo信息的缓存名称;
  • cacheManager:缓存管理器,此处使用EhCacheManager,即Ehcache实现,需要导入相应的Ehcache依赖

测试用例代码如下:

@Test  
public void testClearCachedAuthenticationInfo() {  
    login(u1.getUsername(), password);  
    userService.changePassword(u1.getId(), password + "1");  
  
    RealmSecurityManager securityManager =  
     (RealmSecurityManager) SecurityUtils.getSecurityManager();  
    UserRealm userRealm = (UserRealm) securityManager.getRealms().iterator().next();  
    userRealm.clearCachedAuthenticationInfo(subject().getPrincipals());  
  
    login(u1.getUsername(), password + "1");  
}

首先登录成功(此时会缓存相应的AuthenticationInfo),然后修改密码;此时密码就变了;接着需要调用Realm的clearCachedAuthenticationInfo方法清空之前缓存的AuthenticationInfo;否则下次登录时还会获取到修改密码之前的那个AuthenticationInfo;

@Test  
public void testClearCachedAuthorizationInfo() {  
    login(u1.getUsername(), password);  
    subject().checkRole(r1.getRole());  
    userService.correlationRoles(u1.getId(), r2.getId());  
  
    RealmSecurityManager securityManager =  
      (RealmSecurityManager) SecurityUtils.getSecurityManager();  
    UserRealm userRealm = (UserRealm)securityManager.getRealms().iterator().next();  
    userRealm.clearCachedAuthorizationInfo(subject().getPrincipals());  
  
    subject().checkRole(r2.getRole());  
}  

此处调用Realm的clearCachedAuthorizationInfo清空之前缓存的AuthorizationInfo;
另外还有clearCache,其同时调用clearCachedAuthenticationInfo和clearCachedAuthorizationInfo,清空AuthenticationInfo和AuthorizationInfo。
UserRealm还提供了clearAllCachedAuthorizationInfo、clearAllCachedAuthenticationInfo、clearAllCache,用于清空整个缓存。

Shiro Session缓存

当我们设置了SecurityManager的CacheManager或者SessionManager。如下:

securityManager.cacheManager=$cacheManager
sessionManager=org.apache.shiro.session.mgt.DefaultSessionManager  
securityManager.sessionManager=$sessionManager   

如果securityManager实现了SessionsSecurityManager,其会自动判断SessionManager是否实现了CacheManagerAware接口,如果实现了会把CacheManager设置给它。然后sessionManager会判断相应的sessionDAO(如继承自CachingSessionDAO)是否实现了CacheManagerAware,如果实现了会把CacheManager设置给它;如前一篇的MySessionDAO就是带缓存的SessionDAO;其会先查缓存,如果找不到才查数据库。

对于CachingSessionDAO,可以通过如下配置设置缓存的名称:

sessionDAO=com.xttblog.shiro10.session.dao.MySessionDAO  
sessionDAO.activeSessionsCacheName=shiro-activeSessionCache

activeSessionsCacheName默认就是shiro-activeSessionCache。

本文实例源代码下载链接:http://pan.baidu.com/s/1i5xDhcT 密码:3k8x

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » Shiro 缓存机制