1. 應用場景
在企業級Web應用中, 爲了提高用戶體驗或者遵守一些標準(比如PCI標準), 產品經理常常會提出如下需求:
session過期後, 用戶點擊其它需要權限才能訪問的鏈接時, 頁面應跳轉到登錄頁面, 並提示用戶因爲session過期需要重新登錄.
2. 細節分析與相關技術
怎麼實現呢? 我用很多個關鍵字google了半天, 看到了很多類似的問題, 但沒有找到任何解決方案. 求人不如求己, 分析下需求, 自己找個解決方案吧.
這個需求包含三個細節:
- 如果用戶關閉瀏覽器再訪問需要權限才能訪問的鏈接時, login頁面不應顯示session過期的信息;
- 如果用戶logout後再訪問需要權限才能訪問的鏈接時, login頁面不應顯示session過期的信息;
- 僅當用戶處於不活動(Inactive)狀態一定時間後再訪問需要權限才能訪問的鏈接時, login頁面才顯示session過期的信息;
HTTP請求是無連接的, Session和Cookie是記錄HTTP請求上下文關係的兩種方式. 兩者的主要區別是:
- Cookie由客戶端(Browser)維護, 也就是說session過期後, Cookie依然是存在的, 通過request是可以取到的.
- Session由服務器維護.
顯然這裏是不能使用session的, 因爲session已經過期了. 那麼就要在Cookie上做研究了.
Cookie有兩種:
- Session Cookie
- Persistent Cookie
大家所說的Cookie一般是指Persistent Cooke, 它保存在硬盤上, 可以用文本編輯器打開. Session Cookie與Persistent Cookie的區別是:
- Session Cookie在內存中, 隨着瀏覽器的關閉而消失.
Session Cookie的這個特點很有意思, 和細節1有某種對應.
注: 在J2EE中, 如果不修改Cookie的生命期, 默認的Cookie是Session Cookie.
3. 解決方案
通過以上的分析, 我們可以瞭解到Session Cookie的兩個特點:
- 使用Session Cookie標記用戶是否已經登錄, 由於用戶關閉Browser後Session Cookie消失, 很好地滿足了細節1.
- 由於Cookie由客戶端維護, Session過期後, Session Cookie依然存在, 但Session已經不在了.
基於以上兩個特點, 我們可以採用如下解決方案:
- 當用戶成功登錄後, 向response中添加Session Cookie, 比如HAVE_LOGIN_COOKIE, 表示用戶已經登錄.
- 當用戶退出(Logout)後, 刪除response中的HAVE_LOGIN_COOKIE Cookie.
- 設置Filter, 對所有請求, 當請求中帶有HAVE_LOGIN_COOKIE, 並且request.getSession(false)得到的session爲空時(意味着session已經過期), response重定向到login?session_timeout=1鏈接, 如果session_timeout參數非空且值爲1, 顯示"Session已經過期, 請重新登錄"信息.
4. 參考實現
LoginAction中添加代碼:
LogoutAction中添加代碼:
login.jsp
Filter類:
web.xml配置