Shiro 缓存机制

缓存,我的理解是:让数据更接近于使用者;工作机制是:先从缓存中读取数据,如果没有再从慢速设备上读取实际数据(数据也会存入缓存);缓存什么:那些经常读取且不经常修改的数据/那些昂贵(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

Shiro 缓存机制

: » Shiro 缓存机制

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/251554.html

(0)
上一篇 2022年5月3日
下一篇 2022年5月3日

相关推荐

发表回复

登录后才能评论