shiro实例 缓存之Realm篇

本文详细介绍了Shiro中的缓存机制,包括Cache接口、CacheManager接口及其配置方式。通过spring-shiro.xml配置示例展示了如何设置缓存管理器、Realm缓存等,并解释了ehcache-shiro.xml配置文件中各项参数的意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 信息的缓存。

spring-shiro.xml配置


<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 设置安全管理器的安全数据源为自定义的 Realm -->
        <property name="realm" ref="myRealm"/>
        <property name="cacheManager" ref="cacheManager"/>
        ...
    </bean>

<!-- 配置缓存管理器 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean> 

<bean id="myRealm" class="com.zm.web_shiro.realm.CustomRealm">
        <!-- 配置缓存相关 -->
        <!-- 启用缓存 -->
        <property name="cachingEnabled" value="true"/>
        <!-- 开启认证缓存-->
        <property name="authenticationCachingEnabled" value="true"/>
        <!-- 指定认证缓存的名字(与 ehcache.xml 中声明的相同) -->
        <property name="authenticationCacheName" value="authenticationCache"/>
        <!--开启授权缓存-->
        <property name="authorizationCachingEnabled" value="true"/>
        <!-- 指定授权缓存的名字(与 ehcache.xml 中声明的相同) -->
        <property name="authorizationCacheName" value="authorizationCache"/>
    </bean>

ehcache-shiro.xml


<ehcache>
    <!--diskStore:缓存数据持久化的目录 地址  -->
    <diskStore path="E:\cache\ehcache" />
    <!--<diskStore path="java.io.tmpdir"/>--> <!-- 系统的默认临时文件路径 -->

    <!--  
       name:缓存名称。  
       maxElementsInMemory:缓存最大数目  
       maxElementsOnDisk:硬盘最大缓存个数。   
       eternal:对象是否永久有效,一但设置了,timeout将不起作用。   
       overflowToDisk:是否保存到磁盘,当系统当机时  
       timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。  
       timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。  
       diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.   
       diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。   
       diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。  
       memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。   
       clearOnFlush:内存数量最大时是否清除。  
       memoryStoreEvictionPolicy:  
            Ehcache的三种清空策略;  
            FIFO,first in first out,这个是大家最熟的,先进先出。  
            LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。  
            LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。  
    -->  

    <defaultCache
            maxElementsInMemory="10000"
            maxElementsOnDisk="10000000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
    />
    <!-- 登录记录缓存 锁定10分钟 -->
    <cache name="passwordRetryCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>
    <!-- 并发登陆,管理会话缓存 -->
    <cache name="shiro-activeSessionCache" eternal="false"
           maxElementsInMemory="10000"
           overflowToDisk="true"
           timeToIdleSeconds="0"
           timeToLiveSeconds="0"/>
    <!-- 授权缓存 -->
    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           overflowToDisk="false"
           statistics="true">
    </cache>
    <!-- 认证缓存 -->
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           overflowToDisk="false"
           statistics="true">
    </cache>
</ehcache>

虽然我们在配置文件中设置了缓存能储存多久,但是当我们登出 subject.logout 时,认证和授权缓存全都是会被清除的,这里我重写了父类AuthorizingRealm 的清除方法,用来直观的学习。

@Override
    protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        Cache c = getAuthenticationCache();
        int cacheSize = c.keys().size();
        log.info("清除【认证】缓存之前,【认证】缓存大小:" + cacheSize);
        for(Object o : c.keys()){
            log.info( o + " , " + c.get(o));
        }
        super.clearCachedAuthenticationInfo(principals);
        log.info("调用父类清除【认证】缓存之后");
        for(Object o : c.keys()){
            log.info( o + " , " + c.get(o));
        }

        // 添加下面的代码清空【认证】的缓存
        //User user = (User) principals.getPrimaryPrincipal();
        String username = principals.getPrimaryPrincipal().toString();
        SimplePrincipalCollection spc = new SimplePrincipalCollection(username,getName());
        super.clearCachedAuthenticationInfo(spc);
        log.info("添加了代码清除【认证】缓存之后");
        cacheSize = c.keys().size();
        log.info("【认证】缓存的大小:" + c.keys().size());
        if (cacheSize == 0){
            log.info("说明【认证】缓存被清空了。");
        }
    }

    @Override
    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        Cache c = getAuthorizationCache();
        int cacheSize = c.keys().size();
        log.info("清除【授权】缓存之前,授权】缓存的大小:" + cacheSize);
        for(Object o : c.keys()){
            log.info( o + " , " + c.get(o));
        }
        super.clearCachedAuthorizationInfo(principals);
        log.info("清除【授权】缓存之后");
        cacheSize = c.keys().size();
        log.info("【授权】缓存的大小:" + cacheSize);

        for(Object o : c.keys()){
            log.info( o + " , " + c.get(o));
        }
        if(cacheSize == 0){
            log.info("说明【授权】缓存被清空了。");
        }

    }

我的项目实例:https://gitee.com/zmq1996/web_shiro

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值