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)
以上兩種方法則可以在任意情況下使用。