單點登錄進階:基于芋道(yudao)授權碼模式的單點登錄流程、代碼實現與安全設計

最近遇到需要單點登錄的場景,我使用的是芋道框架,正好它手動實現了OAuth2的功能,可以為單點登錄提供一些幫助,結合授權碼的模式,在改動最小的情況下實現了單點登錄。關鍵業務數據已經隱藏,后續將以以主認證系統業務子系統的場景為例


一、主要流程

授權碼模式(Authorization Code Grant)是OAuth 2.0標準中安全性最高的認證方式,主要通過“一次性授權碼”避免敏感信息(如client_secret)暴露在前端。以下是主認證系統與業務子系統的單點登錄全流程:


1. 用戶觸發跳轉:從主系統到子系統的入口

用戶在主認證系統的頁面中點擊“業務子系統入口”(例如“數據報表系統入口”),觸發單點登錄流程。這一步的核心是用戶主動選擇需要訪問的子系統。


2. 主系統生成并返回授權碼

前端調用主認證系統的授權接口/system/oauth2/authorize,并傳遞業務子系統的標識(如client_id=report-system)。主認證系統完成兩項關鍵操作:

  • 驗證用戶狀態:確認當前用戶已登錄主認證系統,且有權限訪問目標子系統;
  • 生成一次性授權碼:生成僅單次有效的隨機字符串(如code=c36e714f324a43cfb9a75f24e14406c6),并拼接成跳轉URL返回給前端。

返回的JSON示例如下:

{"code": 0,"data": "https://subsystem.example.com/login?code=c36e714f324a43cfb9a75f24e14406c6&state=1","msg": "成功"
}

關鍵設計:授權碼僅單次有效,防止重放攻擊;state參數用于防止CSRF攻擊(本文示例簡化為固定值,實際需動態生成)。


3. 前端重定向至子系統

前端通過瀏覽器重定向(302 Redirect)跳轉到步驟2返回的URL(如https://subsystem.example.com/login?code=...)。此時,業務子系統的前端頁面將接收到URL中的code參數,進入驗證流程。


4. 子系統驗證授權碼并獲取用戶信息

業務子系統的核心任務是通過授權碼向主認證系統驗證其有效性,并獲取用戶身份信息。這一步必須由子系統后端完成(避免client_secret暴露在前端),具體流程如下:

4.1 子系統前端傳遞code至后端

前端從URL中提取code參數,調用子系統后端接口/login/callbackLogin,將code傳遞給后端。

4.2 后端調用主系統驗證接口

子系統后端通過HTTP請求調用主認證系統的/system/oauth2/token接口,傳遞以下參數:

  • client_id:子系統標識(如report-system);
  • client_secret:子系統密鑰(需保密,僅后端持有);
  • grant_type=authorization_code:標識使用授權碼模式;
  • code:步驟2生成的授權碼;
  • redirect_uri:登錄成功后的跳轉地址(需與主認證系統預先配置一致)。

主認證系統驗證通過后,返回用戶信息及訪問令牌(access_token),示例如下:

{"code": 0,"data": {"scope": "all","userId": 194,"subsystemCode": "report-system","subsystemName": "數據報表系統","access_token": "f963b902248646ffa71d27cdc48fd37d","refresh_token": "8d4dfc224e724ceca296c40b2087f7c7","token_type": "bearer","expires_in": 1799},"msg": "成功"
}
4.3 子系統完成用戶登錄

子系統后端通過返回的userIdsubsystemCode查詢本地用戶信息(若用戶不存在需提前同步或注冊),生成子系統的登錄令牌(如JWT),并記錄登錄日志。

關鍵代碼示例(子系統后端)

public AuthLoginRespVO callbackLogin(String code) throws IOException {// 1. 調用主認證系統,用code換取用戶標識(如subsystemCode)String userIdentifier = oAuth2TokenClient.getUserIdByAuthCode(code);// 2. 根據用戶標識查詢本地用戶(需提前維護主系統與子系統的用戶映射)AdminUserDO localUser = userService.getUserByIdentifier(userIdentifier);if (localUser == null) {throw ServiceExceptionUtil.exception(USER_NOT_EXISTS, "用戶未同步至子系統");}// 3. 生成子系統登錄令牌,記錄日志return createTokenAfterLoginSuccess(localUser.getId(), localUser.getUsername(), LoginLogTypeEnum.LOGIN_SSO);
}

5. 子系統生成令牌并跳轉首頁

子系統后端將生成的登錄令牌(如token=abc123)返回給前端,前端攜帶該令牌跳轉到子系統首頁,完成單點登錄。


二、子系統后端的HTTP客戶端實現

子系統后端需要通過HTTP客戶端與主認證系統交互,以下是核心實現類(已簡化):

@Component
public class OAuth2TokenClient {// 從配置文件讀取主認證系統信息(敏感信息需加密存儲)@Value("${sso.base_url}")private String baseUrl; // 主認證系統基礎URL(如http://sso.main-system.com)@Value("${sso.token_url}")private String tokenUrl; // 令牌接口路徑(如/system/oauth2/token)@Value("${sso.client_id}")private String clientId; // 子系統標識@Value("${sso.client_secret}")private String clientSecret; // 子系統密鑰(需保密)@Value("${sso.redirect_url}")private String redirectUri; // 登錄成功跳轉地址private static final ObjectMapper objectMapper = new ObjectMapper();public String getUserIdByAuthCode(String authCode) throws IOException {// 構造POST請求HttpPost httpPost = new HttpPost(baseUrl + tokenUrl);httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");// 組裝請求參數(嚴格遵循OAuth 2.0規范)List<NameValuePair> params = new ArrayList<>();params.add(new BasicNameValuePair("client_id", clientId));params.add(new BasicNameValuePair("client_secret", clientSecret));params.add(new BasicNameValuePair("grant_type", "authorization_code"));params.add(new BasicNameValuePair("code", authCode));params.add(new BasicNameValuePair("redirect_uri", redirectUri));try (CloseableHttpClient client = HttpClients.createDefault();CloseableHttpResponse response = client.execute(httpPost)) {String responseBody = EntityUtils.toString(response.getEntity());JsonNode root = objectMapper.readTree(responseBody);// 校驗主認證系統返回狀態if (root.path("code").asInt() != 0) {throw ServiceExceptionUtil.exception(new ErrorCode(root.path("code").asInt(), root.path("msg").asText()));}// 提取用戶標識(根據主認證系統返回結構調整)return root.path("data").path("subsystemCode").asText();} catch (ParseException e) {throw new RuntimeException("響應解析失敗", e);}}
}
查看全部

三、配置示例

sso:base_url: "http://sso.main-system.com" # 主認證系統基礎URL(替換為實際地址)token_url: "/system/oauth2/token" # 授權碼驗證接口路徑client_id: "report-system" # 子系統標識(需主認證系統預先注冊)client_secret: "subsystem-secret-123" # 子系統密鑰(需加密存儲,避免明文)redirect_url: "http://subsystem.example.com/auto-login" # 登錄成功跳轉地址(需與主認證系統配置一致)

四、子系統前后端協作流程總結

階段前端操作后端操作
接收code從URL參數中提取code-
傳遞code調用/login/callbackLogin接口,傳遞code接收code,調用主認證系統驗證
完成登錄接收后端返回的token生成子系統token,返回前端
跳轉首頁攜帶token跳轉到首頁-

五、注意事項

  1. 授權碼的安全性
    • 授權碼僅單次有效,主認證系統需嚴格校驗其使用狀態,防止重放攻擊;
    • 避免在前端暴露client_secret,所有與主認證系統的交互必須由后端完成。
  2. 用戶映射與同步
    • 主認證系統與子系統需維護用戶關聯關系(如主系統userId=194對應子系統userId=1001),建議通過定時任務或事件通知同步用戶信息;
    • 若用戶未同步至子系統,需明確提示“用戶無權限”或觸發自動注冊流程(需評估安全風險)。
  3. 錯誤處理
    • 主認證系統返回錯誤(如code無效)時,子系統需捕獲異常并返回友好提示(如“登錄失敗,請重新操作”);
    • 記錄詳細的日志(如code、請求時間、錯誤碼),便于排查問題。
  4. 參數校驗
    • 子系統后端需校驗code的格式(如長度、字符類型),防止非法請求;
    • state參數需動態生成并校驗(本文示例簡化,實際需實現),防止CSRF攻擊。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87651.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87651.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87651.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于Seata的一個小issue...

文章目錄 引言原因&#x1f913;解決方法&#x1f635;總結?? 引言 某一天&#xff0c;筆者在逛著Github的時候&#xff0c;突然看到seata有個有趣的issue&#xff0c;是一個task。 相關描述&#xff1a; While running the DruidSQLRecognizerFactoryTest.testIsSqlSynta…

FTTR+軟路由網絡拓撲方案

文章目錄 網絡拓撲軟路由配置FTTR光貓路由器TPLink路由器配置WAN設置LAN設置 參考 網絡拓撲 軟路由配置 配置靜態IP地址&#xff1a;192.168.1.100設置網關指向主路由的IP 設置自定義DNS服務器 開啟DHCP 這一步很關鍵&#xff0c;可以讓連上wifi的所有設備自動趴強。 FTTR光貓…

RPC - 服務注冊與發現模塊

為什么要服務注冊&#xff0c;服務注冊是做什么 服務注冊主要是實現分布式的系統&#xff0c;讓系統更加的健壯&#xff0c;一個節點主機將自己所能提供的服務&#xff0c;在注冊中心進行登記 為什么要服務發現&#xff0c;服務發現是要做什么 rpc調用者需要知道哪個節點主機…

分布式緩存:應對突發流量的緩存體系構建

文章目錄 緩存全景圖Pre背景與目標說明緩存原則與設計思路緩存體系架構緩存預熱與緩存預加載庫存操作與緩存結合防刷、限流與緩存緩存一致性與失效異步落地與消息隊列監控與指標容災與擴展示例小結 緩存全景圖 Pre 分布式緩存&#xff1a;緩存設計三大核心思想 分布式緩存&am…

華為云Flexus+DeepSeek征文|CCE容器高可用部署搭建Dify-LLM平臺部署AI Agent

華為云FlexusDeepSeek征文&#xff5c;CCE容器高可用部署搭建Dify-LLM平臺部署AI Agent 前言 Dify是一款開源的大語言模型應用開發平臺&#xff0c;融合了后端即服務和LLMOps的理念&#xff0c;使開發者可以快速搭建生產級的生成式AI應用&#xff0c;本文將詳細介紹如何使用華…

Postman 的 Jenkins 管理 - 手動構建

目錄 一、準備工作 二、postman 項目腳本準備并導出 1. 打開已完成并測試無誤的 postman 項目腳本。 再次執行測試。 ?編輯2. 導出&#xff08; 測試用例集、環境變量 兩個文件&#xff09;**“不 支 持 中 文”** —— 全部改成英文&#xff01; ?編輯3. 文件所在目錄…

音視頻之H.264/AVC解碼器的原理和實現

系列文章&#xff1a; 1、音視頻之視頻壓縮技術及數字視頻綜述 2、音視頻之視頻壓縮編碼的基本原理 3、音視頻之H.264/AVC編碼器原理 4、音視頻之H.264的句法和語義 5、音視頻之H.264/AVC解碼器的原理和實現 6、音視頻之H.264視頻編碼傳輸及其在移動通信中的應用 7、音視…

【智能安全帽新升級】搭載VTX316TTS語音合成芯片,讓安全“聽得見”!

在工地轟鳴的機械聲中&#xff0c;一句清晰的指令可能比任何文字都更有力量。 當智能安全帽遇上VTX316語音合成芯片&#xff0c;安全防護從“被動響應”進化為“主動交互”&#xff0c;為高危行業戴上了一頂“會說話的智慧大腦”&#xff01; 傳統安全帽的“沉默”危機 在建筑…

【目標檢測】非極大值抑制(NMS)的原理與實現

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

DB-GPT啟動提示please install by running `pip install cryptography`

DB-GPT項目需要 cryptography 庫來處理加密功能&#xff0c;但環境中沒有安裝它。cryptography 是一個用于安全和加密操作的Python庫&#xff0c;許多項目&#xff08;包括DB-GPT&#xff09;依賴它來處理敏感數據的加密存儲。 解決方案 1. 安裝 cryptography 庫 在激活的環…

局域網文件共享及檢索系統

標題:局域網文件共享及檢索系統 內容:1.摘要 隨著信息技術的飛速發展&#xff0c;局域網在企業、學校等場景中得到廣泛應用&#xff0c;大量文件在局域網內存儲和流轉。然而&#xff0c;目前局域網內文件共享與檢索存在效率低、管理困難等問題。本文旨在設計并實現一個高效的局…

Spring Boot醫療系統高并發難題:達夢數據庫死鎖排查與優化實戰

Spring Boot醫療系統高并發難題:達夢數據庫死鎖排查與優化實戰 引言:醫療系統中的并發挑戰 在現代醫療系統中,檢查申請處理是關鍵業務場景之一,每天需要處理數以萬計的檢查記錄。當多個操作同時更新同一患者的申請狀態時,數據庫層面的死鎖問題成為高并發環境下的典型痛點…

Go語言中的文件與IO:bufio 和 scanner

Go 標準庫中的 bufio 包提供了帶緩沖的讀寫功能&#xff0c;可以顯著提高文件和數據處理效率。而 bufio.Scanner 則是讀取文本文件中每一行的利器&#xff0c;常用于日志、配置等文本處理場景。 一、為什么使用 bufio&#xff1f; 直接對文件進行 os.File.Read() 或 os.File.W…

ABP微服務架構中網關層NullReferenceException問題解析與HTTP配置優化

ABP微服務架構中網關層NullReferenceException問題解析與HTTP配置優化 一、網關層System.NullReferenceException問題解析 1.1 問題現象與原因分析 在ABP微服務架構開發過程中&#xff0c;網關層啟動后調用微服務接口時出現以下異常&#xff1a; System.NullReferenceExcep…

啊啊啊啊啊啊啊啊code

前序遍歷和中序遍歷構建二叉樹 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNod…

【算法 day06】LeetCode 454.四數相加II | 15. 三數之和 | 18. 四數之和

454.四數相加II 題目鏈接 | 文檔講解 |視頻講解 : 鏈接 1.思路&#xff1a; 0.定義一個count&#xff0c;計算最終出現的次數 1.先遍歷nums1和nums2,求出兩者的和&#xff0c;map的key是和&#xff0c;value是出現的次數 2.再遍歷nums3和nums4&#xff0c;求出0-兩者的和 3…

【項目實訓】【項目博客#09】HarmonySmartCodingSystem系統后端智能API檢索與代碼助手實現(6.2-6.15)

【項目實訓】【項目博客#09】HarmonySmartCodingSystem系統后端智能API檢索與代碼助手實現&#xff08;6.2-6.15&#xff09; 文章目錄 【項目實訓】【項目博客#09】HarmonySmartCodingSystem系統后端智能API檢索與代碼助手實現&#xff08;6.2-6.15&#xff09;項目博客概述一…

【JVM】- 類加載與字節碼結構3

類加載階段 1. 加載 加載&#xff1a;將類的字節碼載入方法區中&#xff0c;內部采用C的instanceKlass描述java類。如果這個類的父類還沒加載&#xff0c;則先加載父類加載和鏈接可能是交替運行的 通過全限定名獲取字節碼 從文件系統&#xff08;.class 文件&#xff09;、JA…

Qt藍圖式技能編輯器狀態機模塊設計與實現

設計概述 這個模塊是一個基于Qt的藍圖式技能編輯器狀態機&#xff0c;主要用于游戲開發中的技能狀態管理。核心功能包括&#xff1a; 狀態節點&#xff08;開始、結束、普通狀態&#xff09;的可視化 狀態間連線的繪制與管理 狀態轉換邏輯的可視化編輯 動作選擇與配置 核…

Unity AR識別物體的內容語音讀取+使用說明功能

因之前一直在開發項目&#xff0c;斷斷續續寫了一點博客&#xff0c;最后統一寫了一下博客記錄學習內容。 可以看到我的工作一直在進行。 目錄 一、識別內容語音讀取 二、點擊齒輪按鈕彈出使用說明界面 開發步驟 1. 創建齒輪按鈕 UI 2. 創建使用說明面板 UI 3. 編寫控制…