概述
nShiro开发团队明白在许多应用程序中性能是至关重要的。Caching 是Shiro 中的一个重要功能,以确保安全操作保持尽可能的快。
n
n但是,Shiro并不实现缓存的功能,Shiro 的缓存支持基本上是一个抽象的(包装)API,它将“坐”在一个基本的缓存机制产品(例如,Ehcache,OSCache,Terracotta,Coherence,GigaSpaces,JBossCache 等)之上。这允许Shiro终端用户配置他们喜欢的任何缓存机制。
Caching API
nShiro 有三个重要的缓存接口:
1:CacheManager - 负责所有缓存的主要管理组件,它返回Cache 实例 2:Cache - 维护key/value 对 3:CacheManagerAware - 通过想要接收和使用CacheManager 实例的组件来实现
n
nCacheManager 返回Cache 实例,各种不同的Shiro 组件使用这些Cache 实例来缓存必要的数据。任何实现了CacheManagerAware 的Shiro 组件将会自动地接收一个配置好的CacheManager,该CacheManager 能够用来获取Cache 实例。
n
nShiro 的SecurityManager 实现及所有AuthorizingRealm实现都实现了CacheManagerAware
n
nShiro 提供了一个个立即可用的EhCacheManager 实现
Caching
配置
n通过在SecurityManager上设置了CacheManger,它反过来也会将它设置到实现了CacheManagerAware 的各种不同的Realm 上,示例如下:
n
cacheManager = org.apache.shiro.cache.ehcache.EhcacheManager securityManager.cacheManager = $cacheManager
n默认的EHCache使用一个Shiro特定的ehcache.xml文件来配置,大致内容如下:
<cache name="shiro-activeSessionCache" maxElementsInMemory="10000" overflowToDisk="true" eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0" diskPersistent="true" diskExpiryThreadIntervalSeconds="600"/>
包装使用其他的Cache框架
n可以通过写一个类来实现Shiro的CacheManager,在这个类里面包装使用任何你想要使用的Cache框架,这里以使用Srping的缓存框架为例,参考如下:
public class MyCacheManager implements CacheManager { public <K, V> Cache<K, V> getCache(String name) throws CacheException { org.springframework.cache.Cache springCache = cacheManager.getCache(name); return new SpringCacheWrapper(springCache); } class SpringCacheWrapper implements Cache { private org.springframework.cache.Cache springCache; SpringCacheWrapper(org.springframework.cache.Cache springCache) { this.springCache = springCache; } public Object get(Object key) throws CacheException { Object value = springCache.get(key); if (value instanceof SimpleValueWrapper) { return ((SimpleValueWrapper) value).get(); } return value; } //等等,还有几个需要实现的方法,都可以使用你要使用的缓存框架去实现 } }
缓存数据同步更新的解决方案
n使用Shiro的时候,缓存数据最大的问题就在于数据同步更新。
n因为Shiro只负责验证部分,如果应用程序修改了人员的权限,那么就需要同步更新到Shiro里面去,也就是要同步Shiro的缓存数据。
n
n一个解决方案就是完全废弃Shiro的缓存机制,自己在应用中控制数据的缓存
n
n这里给出另一种简易可行的方案:
1:如果你使用的Spring,而且是自定义的Realm,那么可以在你的Realm里面添加一个方法来删除该用户的缓存数据,这样下次shiro在验证这个用户的时候,就会重新去获取数据,从而实现数据的同步 2:由于是自定义的Realm,可以把该对象作为Spring的bean,注入到你的业务对象中,在需要的时候就可以调用该方法来删除shiro的缓存数据了
n示例,比如在前面自定义的MyRealm中,添加如下方法,示例如下:
public void removeUserCache(String userId){ SimplePrincipalCollection pc = new SimplePrincipalCollection(); pc.add(userId, super.getName()); super.clearCachedAuthorizationInfo(pc); }
n然后在HelloAnno中进行测试,示例如下:
1:要注入MyRealm,但注意需要使用getter/setter来注入 2:在main方法中,示例如下: public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloAnno t = (HelloAnno)ctx.getBean("helloAnno"); t.login(); t.t();
t.t();
t.getMr().removeUserCache("javass"); t.t(); } |
|
来自: wayne_liberary > 《Shiro》