1. 程式人生 > >第十章 會話管理(五) 會話驗證

第十章 會話管理(五) 會話驗證

Shiro 提供了會話驗證排程器,用於定期的驗證會話是否已過期,如果過期將停止會話;出於效能考慮,一般情況下都是獲取會話時來驗證會話是否過期並停止會話的;但是如在web環境中,如果使用者不主動退出是不知道會話是否過期的,因此需要定期的檢測會話是否過期,Shiro 提供了會話驗證排程器SessionValidationScheduler來做這件事情。

可以通過如下ini配置開啟會話驗證:

sessionValidationScheduler=org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
sessionValidationScheduler.interval = 3600000
sessionValidationScheduler.sessionManager=$sessionManager
sessionManager.globalSessionTimeout=1800000
sessionManager.sessionValidationSchedulerEnabled=true
sessionManager.sessionValidationScheduler=$sessionValidationScheduler

sessionValidationScheduler : 會話驗證排程器, sessionManager 預設就是使用ExecutorServiceSessionValidationScheduler,其使用JDK的ScheduledExecutorService進行定期排程並驗證會話是否過期;

sessionValidationScheduler.interval:設定排程時間間隔,單位毫秒,預設就是1 小時;

sessionValidationScheduler.sessionManager:設定會話驗證排程器進行會話驗證時的會話管理器;

sessionManager.globalSessionTimeout:設定全域性會話超時時間,預設30 分鐘,即如果30分鐘內沒有訪問會話將過期;

sessionManager.sessionValidationSchedulerEnabled:是否開啟會話驗證器,預設是開啟的;

sessionManager.sessionValidationScheduler: 設定會話驗證排程器,預設就是使用ExecutorServiceSessionValidationScheduler。

Shiro 也提供了使用Quartz會話驗證排程器:

sessionValidationScheduler=org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler
sessionValidationScheduler.sessionValidationInterval = 3600000
sessionValidationScheduler.sessionManager=$sessionManager

使用時需要匯入shiro-quartz依賴:

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.2</version>
</dependency>

如 上會話驗證排程器實現都是直接呼叫AbstractValidatingSessionManager 的validateSessions方法進行驗證,其直接呼叫SessionDAO 的getActiveSessions方法獲取所有會話進行驗證,如果會話比較多,會影響效能;可以考慮如分頁獲取會話並進行驗證,如com.github.zhangkaitao.shiro.chapter10.session.scheduler.MySessionValidationScheduler:

//分頁獲取會話並驗證
String sql = "select session from sessions limit ?,?";
int start = 0; //起始記錄
int size = 20; //每頁大小
List<String> sessionList = jdbcTemplate.queryForList(sql, String.class, start, size);
while(sessionList.size() > 0) {
for(String sessionStr : sessionList) {
try {
Session session = SerializableUtils.deserialize(sessionStr);
Method validateMethod =
ReflectionUtils.findMethod(AbstractValidatingSessionManager.class,
"validate", Session.class, SessionKey.class);
validateMethod.setAccessible(true);
ReflectionUtils.invokeMethod(validateMethod,
sessionManager, session, new DefaultSessionKey(session.getId()));
} catch (Exception e) {
//ignore
}
}
start = start + size;
sessionList = jdbcTemplate.queryForList(sql, String.class, start, size);
}

其直接改造自ExecutorServiceSessionValidationScheduler,如上程式碼是驗證的核心程式碼,可以根據自己的需求改造此驗證排程器器;ini的配置和之前的類似。

如果在會話過期時不想刪除過期的會話,可以通過如下ini配置進行設定:

sessionManager.deleteInvalidSessions=false

預設是開啟的,在會話過期後會呼叫SessionDAO的delete 方法刪除會話:如會話時持久化儲存的,可以呼叫此方法進行刪除。

如果是在獲取會話時驗證了會話已過期,將丟擲InvalidSessionException;因此需要捕獲這個異常並跳轉到相應的頁面告訴使用者會話已過期,讓其重新登入,如可以在web.xml 配置相應的錯誤頁面:

<error-page>
<exception-type>org.apache.shiro.session.InvalidSessionException</exception-type>
<location>/invalidSession.jsp</location>
</error-page>