今天咱們就使用這種方式對 Session 存儲方式進行改造,將其統一存儲到 Redis 中。redis
咱們先來想一下,若是咱們不依靠任何框架,本身如何實現後端 Session 集中存儲。算法
這裏咱們假設咱們的網站除了某些頁面,好比首頁能夠直接訪問之外,其餘任何頁面都須要登陸以後才能訪問。spring
若是須要實現這個需求,這就須要咱們對每一個請求都進行鑑權,鑑權目的是爲了判斷用戶是否登陸,判斷用戶角色。數據庫
若是用戶沒有登陸,咱們須要將請求強制跳轉到登陸頁面進行登陸。json
用戶登陸以後,咱們須要將登陸獲取到的用戶信息存儲到 Session 中,這樣後面請求鑑權只須要判斷 Session 中是否存在便可。後端
知道整個流程以後,其實實現原理就不是很難了。瀏覽器
咱們可使用相似 AOP 的原理,在每一個請求進來以後,都先判斷 Session 中是否存在用戶信息,若是不存在就跳轉到登陸頁。session
整個流程以下所示:app
咱們能夠利用 Servelt Filter 實現上述流程,不過上述整套流程,Spring 已經幫咱們實現了,那咱們就不用重複造輪子了。框架
咱們可使用 Spring-Session 與 Spring-security 實現上述網站的流程。
Spring-Session 是 Spring 提供一套管理用戶 Session 的實現方案,使用 Spring-Session以後,默認 WEB 容器,好比 Tomcat,產生的 Session 將會被 Spring-Session 接管。
除此以外,Spring-Session 還提供幾種常見後端存儲實現方案,好比 Redis,數據庫等。
有了 Spring-Session 以後,它只是幫咱們解決了 Session 後端集中存儲。可是上述流程中咱們還須要登陸受權,而這一塊咱們可使用 Spring-security 來實現。
Spring-security 能夠維護統一的登陸受權方式,同時它能夠結合 Spring-Session 一塊兒使用。用戶登陸受權以後,獲取的用戶信息能夠自動存儲到 Spring-Session 中。
好了,不說廢話了,咱們來看下實現代碼。
下述使用 Spring Boot 實現, Spring-Boot 版本爲:2.3.2.RELEASE
首先咱們引入 Spring Session 依賴,這裏咱們使用 Redis 集中存儲 Session 信息,因此咱們須要下述依賴便可。
若是不是 Spring Boot 項目,那主要須要引入以下依賴:
引入依賴以後,咱們首先須要在 application.properties增長 Session 相關的配置:
配置完成以後,Spring Session 就會開始管理 Session 信息,下面咱們來測試一下:
當咱們訪問上面地址以後,訪問 Redis ,能夠看到存儲的 Session 信息。
默認狀況下,Session 默認使用HttpSession 序列化方式,這種值看起來不夠直觀。咱們能夠將其修改爲 json 序列化方式,存儲到 redis 中。
修改以後 Redis 鍵值以下所示:
ps:這裏 Redis 鍵值含義,下次分析源碼的時候,再作分析。
Spring Session 還存在一個 @EnableRedisHttpSession,咱們能夠在這個註解上配置 Spring Session 相關配置。
@EnableRedisHttpSession(redisNamespace = "test:session")
須要注意的是,若是使用這個註解,將會致使 application.properties Session 相關配置失效,也就是說 Spring Session 將會直接使用註解上的配置。
這裏比較推薦你們使用配置文件的方式。
好了,Spring Session 到這裏咱們就接入完成了。
上面咱們集成了 Spring Session,完成 Session 統一 Redis 存儲。接下來主要須要實現請求的登錄鑑權。
這一步咱們使用 Spring security 實現統一的登錄鑑權服務,一樣的框架的還有 Shiro,這裏咱們就使用 Spring 全家桶。
首先咱們須要依賴的相應的依賴:
引入上面的依賴以後,應用啓動以後將會生成一個隨機密碼,而後全部的請求將會跳轉到一個 Spring security 的頁面。
這裏咱們須要實現本身業務的登錄頁,因此咱們須要自定義登陸校驗邏輯。
在 Spring security 咱們只須要實現 UserDetailsService接口,重寫loadUserByUsername方法邏輯。
上面代碼實現,這裏主要在內存固定用戶名與密碼,真實環境下,咱們須要修改爲從數據庫查詢用戶信息。
接着咱們須要把 UserServiceImpl 配置到 Spring security 中。
上面的配置中,密碼部分咱們使用 BCrypt 算法加密,這裏須要注意,加密與解密須要使用同一種方式。
接着咱們須要實現一個自定義的登錄頁面,這裏就懶得本身寫了,直接使用 spring-session-data-redis 頁面。
這裏須要注意一點,這裏 form 表單的請求地址使用 /auth/login,咱們須要在下面配置中修改,默認狀況下登陸請求的地址須要爲 /login。
接着咱們在上面的 SecurityConfig 類增長相應配置方法:
這個方法可能比較長,重點解釋一下:
最後咱們須要配置一些頁面的跳轉地址:
到此爲止,咱們已經集成 Spring-Session 與 Spring-security 完成完整的網站的登陸鑑權功能。從這個例子能夠看到,引入這個兩個框架以後,咱們只須要按照 Spring 規範開發便可,其餘複雜實現原理咱們都不須要本身實現了,這樣真的很方便