天天看點

Spring Boot系列(十五) 安全架構Apache Shiro(二)緩存-EhCache

本例在上一節Shiro基本功能基礎上增加緩存功能,主要緩存Session、身份、權限等,對于實際應用會減少查詢資料庫次數,提升效率。Shiro為我們提供了CacheManager接口,在1.2.x版本中,提供了EhCache緩存的實作EhCacheManager和預設的MemoryConstrainedCacheManager的實作,到1.3.x版本時,增加了基于Hazelcast的分布式緩存實作HazelcastCacheManager。

通常在單應用中使用EhCache的緩存實作。在上一執行個體基礎上添加EhCache緩存,具體步驟如下:

步驟1:在classpath下添加ehcache.xml配置檔案:/META-INF/ehcache/ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
    <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,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離目前時間最遠的元素将被清出緩存。
    -->
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>
</ehcache>
           

步驟2:在ShiroConfiguration配置類中,建立緩存管理器@Bean

/**
* Shiro CacheManager 定義 Shiro 緩存管理器
* 
* 需要加入到安全管理器:securityManager
* @return
*/
@Bean
public EhCacheManager ehCacheManager() {
    logger.info("注入Shiro的緩存管理器-->ehCacheManager", EhCacheManager.class);
    EhCacheManager cacheManager = new EhCacheManager();
    cacheManager.setCacheManagerConfigFile("classpath:META-INF/ehcache/ehcache.xml");
    return cacheManager;
}
           

步驟3:将緩存管理器注入到SecurityManager中

@Bean
public SecurityManager securityManager() {
    logger.info("注入Shiro的Web過濾器-->securityManager", ShiroFilterFactoryBean.class);
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //設定Realm,用于擷取認證憑證
    securityManager.setRealm(userRealm());
    //注入EhCacheManager緩存管理器
    securityManager.setCacheManager(ehCacheManager());
    return securityManager;
}
           

步驟4:在realm中開啟緩存(預設是false)

@Bean
public UserRealm userRealm() {
    UserRealm userRealm = new UserRealm();
    //告訴realm,使用credentialsMatcher加密算法類來驗證密文
    userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    //啟用緩存,預設false
    userRealm.setCachingEnabled(true);
    //  啟用身份驗證緩存,即緩存AuthenticationInfo資訊,預設false;
    userRealm.setAuthenticationCachingEnabled(true);
    //  緩存AuthenticationInfo資訊的緩存名稱,即配置在ehcache.xml中的cache name
    userRealm.setAuthenticationCacheName("authenticationCache");
    //  啟用授權緩存,即緩存AuthorizationInfo資訊,預設false;
    userRealm.setAuthorizationCachingEnabled(true);
    //  緩存AuthorizationInfo資訊的緩存名稱;
    userRealm.setAuthorizationCacheName("authorizationCache");

    return userRealm;
}
           

測試:

  1. 比如登陸後,1小時不重新整理頁面,session會自動失效(timeToIdleSeconds=”3600”)
  2. 前段擷取角色、權限等資訊,第一次擷取時,回去資料庫查詢(發出sql語句),在有效時間内,再次擷取時,直接從緩存中擷取。

繼續閱讀