Shiro13-Shiro 整合開發(fā)-緩存

解決授權(quán)頻繁查詢數(shù)據(jù)庫問題

緩存流程

shiro 中提供了認(rèn)證信息和授權(quán)信息的緩存.
注意: shiro 默認(rèn)關(guān)閉認(rèn)證信息緩存, 但是對于授權(quán)信息的緩存默認(rèn)是開啟的.

用戶認(rèn)證通過.
該用戶第一次授權(quán): 調(diào)用 realm 查詢數(shù)據(jù)庫.
該用戶第二次授權(quán): 不調(diào)用 realm 查詢數(shù)據(jù)庫, 直接從緩存中取出授權(quán)信息(權(quán)限標(biāo)識符).

使用 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>

創(chuàng)建shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!--diskStore:緩存數(shù)據(jù)持久化的目錄 地址  -->
    <diskStore path="F:\develop\ehcache" />
    <defaultCache 
        <!-- 緩存最大個數(shù) -->
        maxElementsInMemory="1000" 
        <!-- 硬盤最大緩存?zhèn)€數(shù) -->
        maxElementsOnDisk="10000000"
        <!-- 對象是否永久有效,一但設(shè)置了,timeout將不起作用 -->
        eternal="false" 
        <!-- 當(dāng)內(nèi)存中對象數(shù)量達(dá)到maxElementsInMemory時,Ehcache將會對象寫到磁盤中 -->
        overflowToDisk="false" 
        <!-- 是否緩存虛擬機(jī)重啟期數(shù)據(jù) -->
        diskPersistent="false"
        <!--
            設(shè)置對象在失效前的允許閑置時間(單位:秒)。
            僅當(dāng)eternal=false對象不是永久有效時使用,可選屬性,默認(rèn)值是0,也就是可閑置時間無窮大 
        -->
        timeToIdleSeconds="120"
        <!--
            設(shè)置對象在失效前允許存活時間(單位:秒)。
            最大時間介于創(chuàng)建時間和失效時間之間。僅當(dāng)eternal=false對象不是永久有效時使用,默認(rèn)是0.,也就是對象存活時間無窮大。
        -->
        timeToLiveSeconds="120" 
        <!-- 磁盤失效線程運行時間間隔,默認(rèn)是120秒。 -->
        diskExpiryThreadIntervalSeconds="120"
        <!--
            當(dāng)達(dá)到maxElementsInMemory限制時,Ehcache將會根據(jù)指定的策略去清理內(nèi)存。默認(rèn)策略是LRU(最近最少使用)
            你可以設(shè)置為FIFO(先進(jìn)先出)或是LFU(較少使用)
        -->
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

緩存清空

如果用戶正常退出, 緩存自動清空.
如果用戶非正常退出, 緩存自動清空.

如果我們修改了權(quán)限, 而且用戶不退出系統(tǒng), 修改的權(quán)限無法立即生效.
那么如何在修改了權(quán)限之后立即生效呢?
實現(xiàn)思路: 在權(quán)限修改后調(diào)用 realm 的 clearCached() 方法進(jìn)行清除緩存.

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

驗證碼

自定義FormAuthenticationFilter

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {

    //原FormAuthenticationFilter的認(rèn)證方法
    @Override
    protected boolean onAccessDenied(ServletRequest request,
            ServletResponse response) throws Exception {
        //在這里進(jìn)行驗證碼的校驗
        
        //從session獲取正確驗證碼
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpSession session =httpServletRequest.getSession();
        //取出session的驗證碼(正確的驗證碼)
        String validateCode = (String) session.getAttribute("validateCode");
        
        //取出頁面的驗證碼
        //輸入的驗證和session中的驗證進(jìn)行對比 
        String randomcode = httpServletRequest.getParameter("randomcode");
        if(randomcode!=null && validateCode!=null && !randomcode.equals(validateCode)){
            //如果校驗失敗,將驗證碼錯誤失敗信息,通過shiroLoginFailure設(shè)置到request中
            httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
            //拒絕訪問,不再校驗賬號和密碼 
            return true; 
        }
        return super.onAccessDenied(request, response);
    }
}

** 配置自定FormAuthenticationFilter **

<!-- 自定義form認(rèn)證過慮器 -->
<!-- 基于Form表單的身份驗證過濾器,不配置將也會注冊此過慮器,表單中的用戶賬號、密碼及l(fā)oginurl將采用默認(rèn)值,建議配置 -->
    <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>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容