首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

單點登入 (SSO) 流程深度分析:三大核心難題與 Cookie 型解決方案

     編輯:關於.NET

背景:經典 SSO 流程回顧

參考園友文章《單點登陸(SSO)組件的設計與實現》,典型流程:

  1. 用戶訪問子站點 A,無 Session → 重導向認證中心。
  2. 認證中心驗證帳密成功,產生 Token (UID) 存入**認證中心在線列表**,寫入**認證中心 Cookie**。
  3. 重導向回子站點 A,帶上 Token → 子站點驗證 Token 存在於認證中心在線列表 → 建立**子站點 Session** → 登入成功。
  4. 用戶訪問子站點 B,無 Session → 重導向認證中心 → 認證中心發現 Cookie 有效 → 直接重導向回子站點 B 帶 Token → 子站點 B 建立 Session。

三大實戰難題

問題一:Session 過期與在線列表不一致

子站點 A Session 尚未過期,子站點 B Session 已過期,用戶未登出。此時認證中心在線列表該保留還是移除 UID?若移除,A 仍有效卻被判定離線;若保留,B 過期卻仍顯示在線。

問題二:Token 暴露導致身份盜用

URL 參數傳遞 Token (如 ?uid=123) 極易被竊取。攻擊者在另一瀏覽器/機器帶上相同 uid 訪問子站點,認證中心驗證通過 → **橫向越權登入**。

問題三:新分頁/新視窗無法自動識別身份 (核心痛點)

用戶在站點 A 登入後,於**新分頁/新視窗**輸入站點 B 網址。此時:

  • 站點 B **無 Session**(跨域/不同應用程式域)。
  • URL **無 Token 參數**(非重導向進入)。
  • 站點 B **無法得知用戶已在認證中心登入**,導致強制重新登入,體驗極差。

根因分析

SSO 核心難點在於:**如何在「無 Session、無 URL Token」的冷啟動請求中,識別用戶身份?**

答案只有一個:**瀏覽器自動攜帶的 Cookie**。

解決方案:跨域共享 Cookie + 雙重驗證

1. 認證中心設定跨域 Cookie

  • Cookie Domain 設為 **根域名** (如 .example.com)。
  • Cookie Name: SSO_TOKEN,Value: 加密後的 UserId|ExpireTime|Signature。
  • 設定 HttpOnly、Secure、SameSite=Lax。

2. 子站點冷啟動驗證流程

// 子站點 Global.asax / Middleware
public void OnRequest()
{
    // 1. 檢查本地 Session
    if (Session["UserId"] != null) return; // 已登入

    // 2. 檢查 URL Token (重導向回調場景)
    string token = Request.QueryString["token"];
    if (!string.IsNullOrEmpty(token) && ValidateTokenWithAuthCenter(token))
    {
        EstablishLocalSession(token);
        return;
    }

    // 3. 核心:讀取跨域 Cookie
    string ssoCookie = Request.Cookies["SSO_TOKEN"]?.Value;
    if (!string.IsNullOrEmpty(ssoCookie) && ValidateTokenWithAuthCenter(ssoCookie))
    {
        EstablishLocalSession(ssoCookie); // 靜默登入!
        return;
    }

    // 4. 完全未授權 → 重導向認證中心登入頁
    RedirectToAuthCenter();
}

3. 認證中心 Token 驗證邏輯

  • 解密 Cookie → 取得 UserId、ExpireTime、Signature。
  • 檢查 ExpireTime > Now。
  • 驗證簽名 (HMAC-SHA256) 防篡改。
  • 查詢 **在線列表 (Redis/DB)** 確認 UserId 仍在線。
  • 若驗證通過 → 回傳用戶基本資訊 (Id, Name, Roles) 供子站點建立 Session。

4. 解決三大難題

難題解決機制
Session 過期不一致認證中心在線列表 **唯一真實來源**;子站點 Session 只是緩存,過期即重新驗證 Cookie 同步狀態
Token 暴露盜用Cookie HttpOnly 防 XSS 竊取;SameSite=Lax 防 CSRF;簽名防篡改;**綁定 IP/UA 指紋** 進一步降低風險
新分頁無法識別瀏覽器自動攜帶根域 Cookie → 子站點冷啟動即可靜默驗證 → **零感知單點登入**

進階安全強化:IP/裝置指紋綁定

// 產生 Token 時
string fingerprint = Hash(UserIP + UserAgent);
string token = Encrypt($"{userId}|{expire}|{fingerprint}");

// 驗證時
var parts = Decrypt(token).Split('|');
string currentFp = Hash(Request.UserHostAddress + Request.UserAgent);
if (parts[2] != currentFp) throw new SecurityException("Device mismatch");

若用戶 IP 變更 (如切換網路),需重新登入,極大提升安全性。

登出機制:級聯清理

  1. 用戶點擊登出 → 呼叫認證中心 /logout。
  2. 認證中心:刪除在線列表 UID、發送 **刪除 Cookie 指令** (Domain=.example.com, Expires=過去)。
  3. 認證中心重導向各子站點 /sso/logout?token=xxx (或透過 SignalR/WebSocket 推送)。
  4. 子站點收到 → 清除本地 Session、響應刪除 Cookie。

總結

SSO 成敗在於**「冷啟動識別」**。傳統流程依賴重導向傳 Token,無法解決新分頁/新視窗場景。**跨域共享 Cookie + 簽名驗證 + 在線列表二次確認** 是業界標準解法 (如 CAS、IdentityServer、Keycloak 皆採用類似機制)。配合 IP/裝置指紋、短效 Token + Refresh Token、集中式 Session 儲存 (Redis),可構建企業級高安全 SSO 系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved