Sa-Token 是一款 免費、開源 的輕量級 Java 權限認證框架,主要解決:登錄認證、權限認證、單點登錄、OAuth2.0、微服務網關鑑權 等一系列權限相關問題。🔐
目前最新版本 v1.43.0 已推送至 Maven 中央倉庫 🎉,大家可以通過如下方式引入:
<!-- Sa-Token 權限認證 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.43.0</version>
</dependency>
該版本包含大量 ⛏️️️新增特性、⛏️底層重構、⛏️️️代碼優化 等,下面容我列舉幾條比較重要的更新內容供大家參閲:
⛏️️️️ 更新點1:單點登錄模塊新增“單設備註銷”模式
有單點登錄就必然要有單點註銷,目前 SSO 單點登錄模塊包含:單應用註銷、單設備註銷、全端註銷 三種模式,怎麼理解三者的差異呢?
舉個例子,用户在 Chrome 瀏覽器 登錄了 應用A、應用B、應用C,又在 Firefox 瀏覽器登錄了應用A、應用B,那麼此時他:
- 點擊“單應用註銷”後:他只會在應用A註銷下線,其它應用依然會保持登錄狀態。
- 點擊“單設備註銷”後:他在 Chrome 瀏覽器登錄的所有應用會一起下線,但是 Firefox 瀏覽器登錄的應用不受影響。
- 點擊“全端註銷”後:用户在所有瀏覽器登錄的所以會話一起註銷下線。
以上幾種註銷方式僅需通過一行代碼或者調用一個接口即可實現,詳細可參考在線文檔:Sa-Token SSO 單點註銷。
⛏️️️️ 更新點2:單點登錄模塊新增消息推送機制
此提案來源於社區交流羣中的一位開發者諮詢:
該開發者指出是否可以在 SSO 模塊增加各個系統互相通知 token 續期的功能,以便做到系統之間會話有效期的強同步。
本次更新沒有直接增加這兩個 API,而是從底層構建了一套消息推送體系,允許 sso-client 端按照特點格式構建一個 http 請求,調用 sso-server 端的 /sso/pushS 接口,sso-server 接收到消息後做出處理迴應 sso-client 端。
消息推送是相互的,sso-server 端也可以構建 http 請求,調用 sso-client 端的 /sso/pushC 接口。
消息推送機制是應用與認證中心相互溝通的橋樑,ticket 校驗、單點註銷等行為都是依賴消息推送機制來實現的。
當然你也可以通過自定義消息處理器的方式,來擴展消息推送能力,這將非常有助於你完成一些應用與認證中心的自定義數據交互。
假設我們現在有如下需求:在 sso-client 獲取 sso-server 端指定賬號 id 的暱稱、頭像等信息,即:用户資料的拉取。
首先,我們需要在 sso-server 實現一個消息處理器:
@RestController
public class SsoServerController {
// 配置SSO相關參數
@Autowired
private void configSso(SaSsoServerTemplate ssoServerTemplate) {
// 添加消息處理器:userinfo (獲取用户資料) (用於為 client 端開放拉取數據的接口)
ssoServerTemplate.messageHolder.addHandle("userinfo", (ssoTemplate, message) -> {
System.out.println("收到消息:" + message);
// 自定義返回結果(模擬)
return SaResult.ok()
.set("id", message.get("loginId"))
.set("name", "LinXiaoLin")
.set("sex", "女")
.set("age", 18);
});
}
}
在 sso-client 端配置文件裏要配置上消息推送的具體地址
# sa-token配置
sa-token:
# sso-client 相關配置
sso-client:
# 應用標識
client: sso-client3
# sso-server 端推送消息地址
push-url: http://sa-sso-server.com:9000/sso/pushS
# API 接口調用秘鑰
secret-key: SSO-C3-kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
然後在需要拉取資料的地方:
// 查詢我的賬號信息:sso-client 前端 -> sso-center 後端 -> sso-server 後端
@RequestMapping("/sso/myInfo")
public Object myInfo() {
// 如果尚未登錄
if( ! StpUtil.isLogin()) {
return "尚未登錄,無法獲取";
}
// 獲取本地 loginId
Object loginId = StpUtil.getLoginId();
// 構建消息對象
SaSsoMessage message = new SaSsoMessage();
message.setType("userinfo");
message.set("loginId", loginId);
// 推送至 sso-server,並接收響應數據
SaResult result = SaSsoClientUtil.pushMessageAsSaResult(message);
// 返回給前端
return result;
}
詳細可參考在線文檔:Sa-Token SSO 消息推送機制 。
⛏️️️️ 更新點3:單點登錄新增 resdk 對接模式
Sa-Token SSO 模塊一直是支持非 Sa-Token 技術棧、甚至非 java 項目對接的,在之前版本給出的對接方式是 NoSdk 模式。
NoSdk 模式就是指不集成 Sa-Token,直接通過 http 工具類調用接口的方式來對接 SSO-Server。
參考 demo:sa-token-demo-sso3-client-nosdk
該 demo 假設應用端沒有使用任何“權限認證框架”,使用最基礎的 ServletAPI 進行會話管理,模擬了 /sso/login、 /sso/logout、 /sso/logoutCall 三個接口的處理邏輯。
但是基於以下原因,NoSdk 示例將不再維護:
- 1、NoSdk demo 相當於通過 http 工具類再次重寫了一遍 Sa-Token SSO 模塊代碼,繁瑣且冗餘。
- 2、重寫的代碼無法擁有 Sa-Token SSO 模塊全部能力,僅能完成基本對接,算是一個簡化版 SDK。
最新版我們推薦使用 ReSdk 方式進行對接:ReSdk 模式(重寫SDK部分方法):通過重寫框架關鍵步驟點,來對接 SSO-Server。
參考 demo:sa-token-demo-sso3-client-resdk
ReSdk 模式優點:
1、依然支持客户端使用任意技術棧。
2、僅重寫少量部分關鍵代碼,即可完成對接。幾乎可以得到 Sa-Token SSO 模塊全量能力。
⛏️️️️ 更新點4:OAuth2新增多 Access-Token 並存能力。
點擊非常高的一個提案:OAuth2 模塊每次生成新的 access_token 時能否保留舊 access_token 依然有效。
fix issues: #IBHFD1 、 #IBLL4Q 、#724
在之前的版本中,因索引數據結構設計所限,每次申請 access_token 時會導致舊 access_token 立即失效,新版本重構了索引數據結構,增加了多 Access-Token 並存能力。
相關 API 展示:
// 獲取 AccessTokenModel,無效的 AccessToken 會返回 null
SaOAuth2Util.getAccessToken(accessToken);
// 校驗 Access-Token,成功返回 AccessTokenModel,失敗則拋出異常
SaOAuth2Util.checkAccessToken(accessToken);
// 獲取 Access-Token 列表:此應用下 對 某個用户 簽發的所有 Access-token
SaOAuth2Util.getAccessTokenValueList(clientId, loginId);
// 判斷:指定 Access-Token 是否具有指定 Scope 列表,返回 true 或 false
SaOAuth2Util.hasAccessTokenScope(accessToken, ...scopes);
// 校驗:指定 Access-Token 是否具有指定 Scope 列表,如果不具備則拋出異常
SaOAuth2Util.checkAccessTokenScope(accessToken, ...scopes);
// 獲取 Access-Token 所代表的LoginId
SaOAuth2Util.getLoginIdByAccessToken(accessToken);
// 獲取 Access-Token 所代表的 clientId
SaOAuth2Util.getClientIdByAccessToken(accessToken);
// 回收一個 Access-Token
SaOAuth2Util.revokeAccessToken(accessToken);
// 回收全部 Access-Token:指定應用下 指定用户 的全部 Access-Token
SaOAuth2Util.revokeAccessTokenByIndex(clientId, loginId);
在線文檔相關章節:Sa-Token-OAuth2 常用方法
⛏️️️️ 更新點5:簡化 core 核心包功能模塊,進行拆包
在社區羣聊中有同學提到目前 sa-token-core 核心包功能過於擁擠複雜。應要求本次將部分功能模塊進行刪減,轉移到了 plugin 包下:
- 拆分:API Key 模塊拆分獨立插件包:
sa-token-apikey。 - 拆分:API Sign 模塊拆分獨立插件包:
sa-token-sign。
並且本次更新新增了以下插件包:
- 新增:新增
sa-token-forest插件,用於在 Http 請求處理器模塊整合 Forest。 - 新增:新增
sa-token-okhttps插件,用於在 Http 請求處理器模塊整合 OkHttps。
📜 完整更新日誌
除了以上提到的幾點以外,還有更多更新點無法逐一詳細介紹,下面是 v1.43.0 版本的完整更新日誌:
-
core:
- 新增:
SaLogoutParameter新增deviceId參數,用於控制指定設備 id 的註銷。 [重要] - 新增:新增
SaHttpTemplate請求處理器模塊。 - 新增:TOTP 增加
issuer字段。 merge: pr 329 - 修復:修復
Http Digest認證時 url 上帶有查詢參數時認證無法通過的問題。merge: pr 334 - 新增:@SaCheckOr 註解添加
append字段,用於抓取未預先定義的註解類型進行批量註解鑑權。 - 新增:偵聽器
doRenewTimeout方法添加 loginType 參數。 - 新增:
SaInterceptor新增beforeAuth認證前置函數。
- 新增:
-
SSO:
- 新增:單點註銷支持單設備註銷。 [重要] fix: #IA6ZK0 、#747
- 新增:新增消息推送機制。 [重要] fix: #IBGXA7
- 新增:配置項 clients 用於單獨配置每個 client 的授權信息。 [重要]
- 新增:配置項
allowAnonClient決定是否啓用匿名 client。 - 新增:SSO 模塊新增配置文件方式啓用“不同 client 不同秘鑰”能力。
- 重構:sso-client 封裝化獲取 client 標識值。
- 新增:新增 SSO Strategy 策略類。
- 新增:sso-client 新增
convertCenterIdToLoginId、convertLoginIdToCenterId策略函數,用於描述本地 LoginId 與認證中心 loginId 的轉換規則。 - 新增:sso-server 新增
jumpToRedirectUrlNotice策略,用於授權重定向跳轉之前的通知。 - 優化:調整整體 SSO 示例代碼。
- 新增:新增 ReSdk 模式對接示例:
sa-token-demo-sso3-client-resdk。 [重要] - 新增:新增匿名應用模式對接示例:
sa-token-demo-sso3-client-anon。 [重要]
-
OAuth2:
- 新增:
SaClientModel新增isAutoConfirm配置項,用於決定是否允許應用可以自動確認授權。 [重要] - 新增:多
Access-Token並存、多Refresh-Token並存、多Client-Token並存能力。 [重要] fix: #IBHFD1 、 #IBLL4Q 、#724 - 新增:Scope 分割符支持加號。merge: pr 333
- 修復:修復 oidc 協議下,當用户數據變動後,id_token 仍是舊信息的問題。
- 優化:對
OAuth2 Password認證模式需要重寫處理器添加強提醒。 - 優化:將認證流程回調從
SaOAuth2ServerConfig轉移到SaOAuth2Strategy。 - 新增:新增
SaOAuth2Strategy.instance.userAuthorizeClientCheck策略,用於檢查指定用户是否可以授權指定應用。fix: #553 - 優化:優化調整
sa-token-oauth2模塊代碼結構及註釋。 - 新增:
currentAccessToken()、currentClientToken(),簡化讀取access_token、client_token步驟
- 新增:
-
插件:
- 新增:新增
sa-token-forest插件,用於在 Http 請求處理器模塊整合 Forest。 - 新增:新增
sa-token-okhttps插件,用於在 Http 請求處理器模塊整合 OkHttps。 - 拆分:API Key 模塊拆分獨立插件包:
sa-token-apikey。 - 拆分:API Sign 模塊拆分獨立插件包:
sa-token-sign。 - 修復:修復
sa-token-dubbo插件部分場景上下文控制出錯的問題。 - 修復:修復
sa-token-sanck3SaSessionForSnack3Customized:getModel接收 map 值時會出錯的問題。 merge: pr 330 - 修復:修復使用
sa-token-redis-template-jdk-serializer時反序列化錯誤。merge: pr 331 - 修復:
sa-token-snack3優化objectToJson序列化處理(增加類名,但不增加根類名)。 - 重構:重構
sa-token-redis-template、sa-token-redis-template-jdk-serializer插件中 update 方法 ttl 獲取方式改為毫秒,以減少 update 時的 ttl 計算誤差。 [重要]
- 新增:新增
-
示例:
- 新增:新增 SSE 鑑權示例。
-
文檔:
- 新增:新增文檔離線版下載。
- 新增:新增框架功能列表插圖。
- 新增:新增示例:如何在響應式環境下的 Filter 裏調用 Sa-Token 同步 API。
- 新增:新增 QA:在 idea 導入源碼,運行報錯:java: 程序包cn.dev33.satoken.oauth2不存在。
- 新增:新增 QA:新增QA:報錯:SaTokenContext 上下文尚未初始化。
- 新增:新增 QA:在 idea 導入源碼,運行報錯:java: 程序包cn.dev33.satoken.oauth2不存在。
- 新增:重寫路由匹配算法修正為最新寫法。
- 新增:修復 OAuth2 UnionId 章節相關不正確描述。
- 優化:完善 QA:訪問了一個不存在的路由,報錯:SaTokenContext 上下文尚未初始化。 fix: #771
- 優化:補充 sso 模塊遺漏的配置字段介紹。
- 優化:OAuth2-Server 示例添加真正表單。
- 新增:文檔新增重寫
PasswordGrantTypeHandler處理器示例。 - 新增:sso 章節和 oauth2 章節文檔增加可重寫策略説明。
-
其它:
- 新增:readme 新增框架功能介紹圖。
- 新增:SSO 模塊新增思維導圖説明。
- 新增:readme 新增 Forest 的友情鏈接。
更新日誌在線文檔直達鏈接:https://sa-token.cc/doc.html#/more/update-log
🌟 其它
代碼倉庫地址:https://gitee.com/dromara/sa-token