Apache Shiro Session Management學習筆記

Shiro的session並不依賴於web或者EJB的服務架構。

特點:

    1.良好的兼容性,支持IOC,兼容json、yaml、spring xml配置。組件擁有良好的拓展性。

    2.Shiro的session基於POJO,可以很方便的存儲於文件、緩存、關係型數據庫、配置文件。

    3.session的取值過程完全獨立,並不依賴於容器。

    4.session的存在獨立,不依賴於web或者EJB機構。

    5.事件監聽機制。

    6.session會記錄開始ip。

    7.session回收機制,可以通過touch()方法來案場session的生命週期。

    8.Shiro的session和http的session是兼容的。

    9.支持SSO(單點登錄)。


創建session

Subject currentUser = SecurityUtils.getSubject();

Session session = currentUser.getSession();
session.setAttribute( "someKey", someValue);

    Shiro的getSession方法和HttpServletRequest的getSession方法相似:

    1.如果存在相應session,Boolean型標記忽略,立即返回;

    2.如果不存在相應session,Boolean型標記爲true,則創建新的session並返回;

    3.如果不存在相應session,Boolean型標記爲false,則不創建session,返回null。


sessionManagement同樣可以在shiro.ini中配置

[main]
...
sessionManager = com.foo.my.SessionManagerImplementation
securityManager.sessionManager = $sessionManager

session設置超時

[main]
...
# 3,600,000 milliseconds = 1 hour
securityManager.sessionManager.globalSessionTimeout = 3600000

設置session事件監聽兩種方式(shiro.ini):

    1.實現SessionListener接口。

    2.繼承SessionListenerAdapter類。

[main]
...
aSessionListener = com.foo.my.SessionListener
anotherSessionListener = com.foo.my.OtherSessionListener

securityManager.sessionManager.sessionListeners = $aSessionListener, $anotherSessionListener, etc.


關於session的持久化的操作(shiro.ini):

[main]
...
sessionDAO = com.foo.my.SessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

    上述方法只限定於本地session管理,如果是基於web的應用,則需要首先配置本地sessionManager

[main]
...
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager

# Configure a SessionDAO and then set it:
securityManager.sessionManager.sessionDAO = $sessionDAO


session的緩存處理機制(需要導入shiro-ehcache-<version>.jar文件):

    配置方法一:

#This implementation would use your preferred distributed caching product's APIs:
activeSessionsCache = my.org.apache.shiro.cache.CacheImplementation

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCache = $activeSessionsCache

securityManager.sessionManager.sessionDAO = $sessionDAO

    配置方法二(一般使用):

[main]

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
securityManager.cacheManager = $cacheManager

    ehcache.xml中的配置

<cache name="shiro-activeSessionCache"
       maxElementsInMemory="10000"
       overflowToDisk="true"    //內存耗盡時,將session序列化到磁盤,必須屬性
       eternal="true"           //緩存永不過期,而且不會自動刪除,必須屬性
       timeToLiveSeconds="0"
       timeToIdleSeconds="0"
       diskPersistent="true"
       diskExpiryThreadIntervalSeconds="600"/>

    關於配置中的name,shiro-activeSessionCache的更改,需要在EnterpriseCacheSessionDAO中進行配置(shiro.ini)

[main]
...
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCacheName = myname
...


Shiro的默認session的id是由JavaUuidSessionIdGenerator所產生,可以根據需要在配置中改變(shiro.ini):

[main]
...
sessionIdGenerator = com.my.session.SessionIdGenerator
securityManager.sessionManager.sessionDAO.sessionIdGenerator = $sessionIdGenerator


session的回收機制,默認的回收機制不符合需求的話,可以自行設置(shiro.ini):

[main]
...
sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
# Default is 3,600,000 millis = 1 hour:
sessionValidationScheduler.interval = 3600000

securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler

    如果想要自己實現回收,也可以設置爲:

[main]
...
sessionValidationScheduler = com.foo.my.SessionValidationScheduler
securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler

    

如果不需要回收機制的情況下,可以設置(關閉回收機制,需要新的週期性處理無效session的機制,否則會內存溢出。shiro.ini):

[main]
...
securityManager.sessionManager.sessionValidationSchedulerEnabled = false

如果不需要session的刪除機制,也可以設置關閉(需自行刪除無效session。shiro.ini):  

[main]
...
securityManager.sessionManager.deleteInvalidSessions = false

    關閉回收機制和關閉刪除機制的不同之處在於,回收機制關閉必須有其他形式的週期性會話驗證機制來代替。


Ehcache + Terracotta集成案例(ehcache.xml):

<ehcache>
    <terracottaConfig url="localhost:9510"/>
    <diskStore path="java.io.tmpdir/shiro-ehcache"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="false"    //必須爲false,此設置不支持集羣配置
        diskPersistent="false"    //必須爲false,此設置不支持集羣配置
        diskExpiryThreadIntervalSeconds="120">
        <terracotta/>
   </defaultCache>
   <cache name="shiro-activeSessionCache"
       maxElementsInMemory="10000"
       eternal="true"
       timeToLiveSeconds="0"
       timeToIdleSeconds="0"
       diskPersistent="false"
       overflowToDisk="false"
       diskExpiryThreadIntervalSeconds="600">
       <terracotta/>
   </cache>
   <!-- Add more cache entries as desired, for example,
        Realm authc/authz caching: -->
</ehcache>

    此處shiro.ini配置

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
# This name matches a cache name in ehcache.xml:
sessionDAO.activeSessionsCacheName = shiro-activeSessionsCache
securityManager.sessionManager.sessionDAO = $sessionDAO

# Configure The EhCacheManager:
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml

# Configure the above CacheManager on Shiro's SecurityManager
# to use it for all of Shiro's caching needs:
securityManager.cacheManager = $cacheManager    //配置在最後,使cacheManager可以傳播至前面的配置


禁用Shiro內部的session存儲機制,但是並不影響session的產生(shiro.ini):

[main]
...
securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false
...


對於部分需要產生session,部分不需要的情況,可以通過實現org.apache.shiro.mgt.SessionStorageEvaluator接口來對subject進行定製:

...
    public boolean isSessionStorageEnabled(Subject subject) {
        boolean enabled = false;
        if (WebUtils.isWeb(Subject)) {
            HttpServletRequest request = WebUtils.getHttpRequest(subject);
            //set 'enabled' based on the current request.
        } else {
            //not a web request - maybe a RMI or daemon invocation?
            //set 'enabled' another way...
        }

        return enabled;
    }

   shiro.ini中需要配置

[main]
...
sessionStorageEvaluator = com.mycompany.shiro.subject.mgt.MySessionStorageEvaluator
securityManager.subjectDAO.sessionStorageEvaluator = $sessionStorageEvaluator

...


web項目中Shiro的noSession過濾器的配置:

[urls]
...
/rest/** = noSessionCreation, authcBasic, ...

    過濾器將阻止新的session的產生,但是對於已經存在的任然可以繼續使用:

    1.httpServletRequest.getSession();

    2.httpServletRequest.getSession(true);

    3.subject.getSession();

    4.subject.getSession(true)。

    以上四種方法在己經有相應session存在時,可以正常使用;否則會拋出DisabledSessionException異常。

    1. httpServletRequest.getSession(false)

    2.subject.getSession(false)

    以上兩種方法則可以在任意情況下使用。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章