Shiro中Session和Cookie的一些思考 頂 原 薦

這篇博客就來寫一寫之前學習shiro框架整合的時候,產生的一些問題,相信大家在學習的時候也有相應的一些疑惑。接下來就針對shiro中的session和cookie來捋一捋。

shiro整合學習的總結


  1. shiro+redis集成,避免每次訪問有權限的鏈接都會去執行MyShiroRealm.doGetAuthenticationInfo()方法來查詢當前用戶的權限,因爲實際情況中權限是不會經常變得,這樣就可以使用redis進行權限的緩存。

  2. 實現shiro鏈接權限的動態加載,之前要添加一個鏈接的權限,要在shiro的配置文件中添加filterChainDefinitionMap.put(“/add”, “roles[100002],perms[權限添加]”),這樣很不方便管理,一種方法是將鏈接的權限使用數據庫進行加載,另一種是通過init配置文件的方式讀取。

  3. Shiro 自定義權限校驗Filter定義,及功能實現。

  4. Shiro Ajax請求權限不滿足,攔截後解決方案。這裏有一個前提,我們知道Ajax不能做頁面redirect和forward跳轉,所以Ajax請求假如沒登錄,那麼這個請求給用戶的感覺就是沒有任何反應,而用戶又不知道用戶已經退出了。

  5. 控制同一個用戶的在線數量。(擠出之前的登錄用戶)

  6. Shiro 登錄後跳轉到最後一個訪問的頁面

  7. 在線顯示,在線用戶管理(踢出登錄)。

  8. 登錄註冊密碼加密傳輸。

  9. 集成動態驗證碼。

  10. 記住我的功能。關閉瀏覽器後還是登錄狀態。

·······················································································································································

個人博客:http://z77z.oschina.io/

此項目下載地址:https://git.oschina.net/z77z/springboot_mybatisplus

·······················································································································································

session


session是大家比較熟悉的功能,因爲HTTP協議是無狀態的,網站爲了在多個請求之間傳遞數據就使用了session這個東西,session是存儲在網站服務器上的某個地方,比如內存、數據庫或者其他的什麼東西,在我的配置中是用redis存儲的,因爲我使用了Shiro的Native Session Manager,替代了Tomcat本身的Session Manager,並且爲Shiro的Native Session Manager配置了redis的SessionDAO,當然這個我是直接使用的一個開源插件,裏面已經幫我們很好的實現了cacheManager,sessionManager,redisSessionDAO這些。直接使用就可以了。

shiro_redis插件地址:http://www.oschina.net/p/shiro-redis

所以所有的session會話都是緩存在redis裏面的。對session的增刪改查都是在操作redis數據庫來完成。所以如果將redis進行集羣的話,session會話也就會達到集羣的目的。後面我專門寫博客來分享。

在這種情況下服務器的Session就存儲在redis裏面,如果某個Session過期(比如關閉了瀏覽器或者超時),此條Session就會從redis裏面永久刪除,下次的請求將不能使用Session裏面的數據。所以說即使有些url設置的是”user”級別的(也就是說不用登錄即可訪問,只須設置了rememberMe),但是如果這些url使用了Session裏面的數據,就會拋出異常,因爲此時這個用戶對應的Session已經不存在了。

cookie


當瀏覽一個網站的時候,網站返回給你一個Session Cookie和一個RememberMe Cookie,Session Cookie很好理解,就是爲了此次的對話,一旦關閉了瀏覽器或者超時了Session Cookie就沒用了。但是RememberMe Cookie不太一樣,Shiro默認的RememberMe Cookie的時長是一年,所以不用擔心這個Cookie的情況。RememberMe Cookie實際就是Shiro把這個用戶的信息加密一下放到cookie裏面,下次就可以根據這個cookie來進行判斷這是哪個用戶。

主要講下shiro的rememberMe cookie。在shiro中有一個類實現了rememberMe功能, org.apache.shiro.web.mgt.CookieRememberMeManager 。在登錄時,代碼也很簡單:

UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    	token.setRememberMe(true);
    	subject.login(token);

RememberMe這個參數設置爲true後,在登陸的時候就會在客戶端設置remenberme的相應cookie。下次訪問帶上這個cookie,訪問鏈接爲user鏈接器的,就不需要進行登錄驗證,直接進入權限驗證。下面是完整的處理過程:

  • 得到principals對象
  • 通過配置的key,使用aes加密
  • 將加密後的值再通過base64解密
  • 當客戶端帶着這個rememberMe cookie訪問時,將會按照下面的過程來尋找已記住的身份信息:
  • 獲取rememberMe cookie的值
  • Base64解碼
  • 使用AES解密
  • 使用ObjectInputStream進行反序列化

這樣不需要進入身份驗證的攔截器,就直接從cookie中獲取到了登錄信息。

未解決疑惑


session整個流程很好理解,我們使用的插件,對session的操作理解可以去看我之前寫的在線用戶管理和控制在線人數功能,基本都是對session的操作。

https://my.oschina.net/z707z/blog/852189

對於cookie我又下面幾點疑惑,忘大神指點:

  1. 我在測試的時候,使用了remenberme的功能後,我將登錄生成的cookie複製出來,我不管重新登錄相同用戶多少次,我帶上這個cookie訪問的時候,還是不會走身份驗證這個攔截器。只走權限驗證的攔截器,也就是說用戶在使用退出登錄後。之前的cookie還是有效的。並沒有清除。怎麼清除cookie。不是所清除客戶端的cookie,而是清除服務器記住的cookie序列化文件。

  2. 有沒有什麼好的方法可以防止盜取cookie,進行xss攻擊。

網上找了一個思路:

  1. 用戶選擇了 “記住我” 成功登錄後,將會把 username、隨機產生的序列號、生成的 token 存入一個數據庫表中,同時將它們的組合生成一個 cookie 發送給客戶端瀏覽器。
  2. 當下一次沒有登錄的用戶訪問系統時,首先檢查 cookie,如果對應 cookie 中包含的 username、序列號和 token 與數據庫中保存的一致,則表示其通過驗證,系統將重新生成一個新的 token 替換數據庫中對應組合的舊 token,序列號保持不變,同時刪除舊的 cookie,重新生成包含新生成的 token,就的序列號和 username 的 cookie 發送給客戶端。
  3. 如果檢查 cookie 時,cookie 中包含的 username 和序列號跟數據庫中保存的匹配,但是 token 不匹配。這種情況極有可能是因爲你的 cookie 被人盜用了,由於盜用者使用你原本通過認證的 cookie 進行登錄了導致舊的 token 失效,而產生了新的 token。這個時候 shiro就可以發現 cookie 被盜用的情況,它將刪除數據庫中與當前用戶相關的所有 token 記錄,這樣盜用者使用原有的 cookie 將不能再登錄,同時提醒用戶其帳號有被盜用的可能性。
  4. 如果對應 cookie 不存在,或者包含的 username 和序列號與數據庫中保存的不一致,那麼將會引導用戶到登錄頁面。

這樣處理有一個不好的地方就是:必須要每次用戶要再次操作的時候纔會發現cookie被盜用,如果被盜用的cookie是用戶最後一次操作生成的cookie吶。

我到覺得控制用戶登錄人數爲只能一個人登錄一個帳號,還比上面這個方便些,不會反覆的生成cookie,寫入cookie。但是也不好,沒有解決服務器上的cookie沒有根據用戶的退出而失效的這個問題。

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