最近小明遇到一個需求:須要將幾個獨立的系統(子系統)彙總到一個集中的系統(父系統)當中,當用戶在父系統登陸事後,再點擊這幾個子系統,就能夠免登陸跳轉到任意一個系統。當時一聽,duang~duang~就有不少方案涌進來(吹牛的),但只有下面這個方案獲得了leader的確定,現在已經在線上跑着了,接下來給你們覆盤一下。前端
看完這個需求,你們是否是第一感受就是:這不就是SSO(單點登陸)系統嘛?程序員
單點登陸(英語:Single sign-on,縮寫爲 SSO),又譯爲單一簽入,一種對於許多相互關連,可是又是各自獨立的軟件系統,提供訪問控制的屬性。當擁有這項屬性時,當用戶登陸時,就能夠獲取全部系統的訪問權限,不用對每一個單一系統都逐一登陸。這項功能一般是以輕型目錄訪問協議(LDAP)來實現,在服務器上會將用戶信息存儲到LDAP數據庫中。相同的,單一退出(single sign-off)就是指,只須要單一的退出動做,就能夠結束對於多個系統的訪問權限。redis
是的,沒錯,小明接到這個需求之後,總體思路也是按着SSO設想的,可是細想以後,發現不能徹底照搬,要考慮項目的實際狀況:好比已知的幾個子系統是以前的已經開發好的,不能大動干戈,須要平滑接入父系統,並且根據需求,SSO的功能也不必所有實現,簡而言之,就是一個閹割版的SSO。spring
小明只須要實現:用戶在父系統帳號密碼登陸後,經過點擊任意一個子系統的功能按鈕(不須要重複輸入帳號登陸)可以跳轉子系統功能頁便可。數據庫
一個簡單樸素的SpringBoot項目json
說幹就幹,用戶輸入帳號密碼,請求SSO用戶登陸模塊進行帳號密碼校驗,校驗經過後創建全局會話,而且返回前端token憑證(我使用的是sessionId),跳轉其餘系統時攜帶token,其餘系統拿到token後,再調用SSO平臺進行token校驗,若是校驗經過,則用戶可在子系統內創建會話,用戶跳轉系統完成。下面給你們舉例SSO跳轉一個子系統的時序圖:後端
在這裏插一嘴哈,我使用的流程圖工具是ProcessOn,是一款在線畫圖工具,很是適合畫各類示意圖,體驗極佳,若是你們想嘗試一下,可使用個人邀請連接註冊使用~服務器
整個流程圖如上面所示,下面主要針對各個功能點進行詳細說明。微信
本次會話管理採用的是redis session,spring完美支持redis存儲session信息,此外還支持MONGODBJDBCHAZELCAST等存儲會話方式。經過redis存儲session,能夠知足集羣部署、分佈式系統的session共享(固然這些都是後話)。session
pom.xml依賴配置以下
<!--redis 依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--sessions 依賴-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>複製代碼
application.yml配置redis及session
spring:
redis:
host: 127.0.0.1
password: 123456
port: 6379
timeout: 1500
database: 0
jedis:
pool:
max-active: 1000
max-wait: -1
max-idle: 10
min-idle: 5
# 設置session存儲類型爲redis
session:
store-type: redis複製代碼
此時,redis存儲會話配置已經完成,但總以爲缺乏什麼,嗷,原來除此以外,咱們還須要設置session的有效時長,application.yml中的配置以下:
server:
servlet:
session:
# 支持Duration表達式,此時表示120分鐘
timeout: PT120M複製代碼
固然,咱們還須要在Springboot主方法經過@EnableRedisHttpSession
開啓redis session
注意:若是上面配置的session有效時長不生效,咱們能夠在註解屬性上配置session有效時間(不瞞你們,我就是在此處配置才生效的)
@SpringBootApplication
// 開啓redis session ,而且設置session有效時長
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 7200)
public class XiaoMingApplication {
public static void main(String[] args) {
SpringApplication.run(XiaoMingApplication.class, args);
}
}複製代碼
至此,sso系統的登陸及會話管理就完成啦。接下來看一下與其餘系統如何交互。
若是SSO已經登陸 -> 用戶點擊某個子系統按鈕(和負責A系統的人員約定好的連接)發起get請求 -> A系統後端接收到請求 -> 調用SSO系統進行token校驗(下面會講到) -> 創建會話,例如
http://xxx/jump?token=123456複製代碼
這是一個在地址欄輸入的get請求,該接口須要特殊處理,後端攔截器須要放行。
參數 |
說明 |
---|---|
xxx |
此處xxx爲域名,jump爲系統A提供的接口url地址,能夠自定義,須要約定告知 |
token | 返回的校驗憑證 |
該接口其實就須要幹兩件事情:
上面講到SSO會暴漏一個token校驗接口,這一塊邏輯很簡單,就是拿着token去redis中查找對應的用戶信息是否存在。衆所周知,小明是一個懶人,爲了投機取巧,小明token的生成規則,就是session的id,所以,判斷用戶是否登陸,其實就是根據sessionId查找redis是否存在會話,此處有亮點。經過查看源碼,我發現這個功能,根本不用咱們本身去實現,spring已經想到咱們會用到。
spring提供了一個接口org.springframework.session.SessionRepository
package org.springframework.session;
public interface SessionRepository<S extends Session> {
S createSession();
void save(S var1);
// 這個就是
S findById(String var1);
void deleteById(String var1);
}複製代碼
其中S findById(String var1)
就是咱們要調用的方法,這個方法做用就是根據sessionId去會話中心查找會話對象,正是咱們所須要的,咱們只需經過@Autowired
獲取,開箱即用~咱們一塊兒看一下業務代碼:
@Autowired
private SessionRepository sessionRepository;
@PostMapping("/checkToken")
public BaseResponseFacade checkToken(@RequestBody UserLoginVo userLoginVo) {
if (Objects.isNull(userLoginVo)) {
return ResponseUtil.error(NEED_LOGIN);
}
String token = userLoginVo.getToken();
Session session = sessionRepository.findById(token);
if (Objects.isNull(session)) {
return ResponseUtil.error(NEED_LOGIN);
}
AdverInfo adverInfo = JSON.parseObject(session.getAttribute("adverInfo"), AdverInfo.class);
return ResponseUtil.success(adverInfo);
}
SSO和子系統的交互文檔也貼出來給你們一睹爲快複製代碼
{
"token": "123456"
}複製代碼
參數 |
說明 |
---|---|
xxx/checkToken | xxx爲域名,checkToken爲營銷雲平臺提供的校驗接口地址 |
token |
調用接口憑據 |
返回說明
若是SSO校驗經過,則系統A能夠與與當前用戶創建本地會話,用戶正常進入系統
{
"data":{
"XXX":"XXX"
},
"errorMsg":"成功",
"errorCode":0
}複製代碼
參數說明
參數 |
說明 |
---|---|
errorCode | 0:表示請求成功 |
errorMsg |
返回碼說明 |
XXX |
其餘相關信息 |
當SSO後臺校驗失敗時返回參數以下
{
"errorMsg": "NEED_LOGIN",
"errorCode": 10
}複製代碼
參數說明
參數 |
說明 |
---|---|
errorMsg |
錯誤信息說明 |
errorCode | 錯誤標誌 |
錯誤碼說明
錯誤碼 | 說明 |
---|---|
1 |
系統繁忙 |
10 |
須要用戶登陸 |
500 |
服務器內部錯誤 |
小明設計的簡潔版sso就大抵如此,你們能夠做爲一個sso入門demo來看待😁,若是你們有什麼建議或問題,歡迎留言~你們也能夠關注微信公衆號「程序員小明」獲取更多資源~歡迎關注微信公衆號」程序員小明」,獲取更多資源。