Shiro13-Shiro 整合开发-缓存

解决授权频繁查询数据库问题

缓存流程

shiro 中提供了认证信息和授权信息的缓存.
注意: shiro 默认关闭认证信息缓存, 但是对于授权信息的缓存默认是开启的.

用户认证通过.
该用户第一次授权: 调用 realm 查询数据库.
该用户第二次授权: 不调用 realm 查询数据库, 直接从缓存中取出授权信息(权限标识符).

使用 ehcache

在 spring-shiro.xim 中配置 cacheManager

<!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="customRealm" />
    <!-- 注入缓存管理器 -->
    <property name="cacheManager" ref="cacheManager"/>
</bean>

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

创建shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!--diskStore:缓存数据持久化的目录 地址  -->
    <diskStore path="F:\develop\ehcache" />
    <defaultCache 
        <!-- 缓存最大个数 -->
        maxElementsInMemory="1000" 
        <!-- 硬盘最大缓存个数 -->
        maxElementsOnDisk="10000000"
        <!-- 对象是否永久有效,一但设置了,timeout将不起作用 -->
        eternal="false" 
        <!-- 当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中 -->
        overflowToDisk="false" 
        <!-- 是否缓存虚拟机重启期数据 -->
        diskPersistent="false"
        <!--
            设置对象在失效前的允许闲置时间(单位:秒)。
            仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大 
        -->
        timeToIdleSeconds="120"
        <!--
            设置对象在失效前允许存活时间(单位:秒)。
            最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
        -->
        timeToLiveSeconds="120" 
        <!-- 磁盘失效线程运行时间间隔,默认是120秒。 -->
        diskExpiryThreadIntervalSeconds="120"
        <!--
            当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)
            你可以设置为FIFO(先进先出)或是LFU(较少使用)
        -->
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

缓存清空

如果用户正常退出, 缓存自动清空.
如果用户非正常退出, 缓存自动清空.

如果我们修改了权限, 而且用户不退出系统, 修改的权限无法立即生效.
那么如何在修改了权限之后立即生效呢?
实现思路: 在权限修改后调用 realm 的 clearCached() 方法进行清除缓存.

//清除缓存
public void clearCached() {
    PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
    super.clearCache(principals);
}

验证码

自定义FormAuthenticationFilter

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {

    //原FormAuthenticationFilter的认证方法
    @Override
    protected boolean onAccessDenied(ServletRequest request,
            ServletResponse response) throws Exception {
        //在这里进行验证码的校验
        
        //从session获取正确验证码
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpSession session =httpServletRequest.getSession();
        //取出session的验证码(正确的验证码)
        String validateCode = (String) session.getAttribute("validateCode");
        
        //取出页面的验证码
        //输入的验证和session中的验证进行对比 
        String randomcode = httpServletRequest.getParameter("randomcode");
        if(randomcode!=null && validateCode!=null && !randomcode.equals(validateCode)){
            //如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
            httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
            //拒绝访问,不再校验账号和密码 
            return true; 
        }
        return super.onAccessDenied(request, response);
    }
}

** 配置自定FormAuthenticationFilter **

<!-- 自定义form认证过虑器 -->
<!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 -->
    <bean id="formAuthenticationFilter" 
    class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter ">
        <!-- 表单中账号的input名称 -->
        <property name="usernameParam" value="username" />
        <!-- 表单中密码的input名称 -->
        <property name="passwordParam" value="password" />
 </bean>
        <!-- 自定义filter配置 -->
        <property name="filters">
            <map>
                <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->
                <entry key="authc" value-ref="formAuthenticationFilter" />
            </map>
        </property>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容