單點登錄本質是身份憑證共享。Forms 認證基於加密 Cookie(FormsAuthenticationTicket),實現 SSO 的關鍵在於讓多個應用能夠讀取、驗證同一張身份 Cookie。
例子:app1.domain.com、app2.domain.com 共享 .domain.com 域 Cookie
// 1. 序列化用戶數據
string userData = JsonHelper.Serialize(user);
// 2. 創建認證票據
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // 版本
user.UserId.ToString(), // 用戶標識
DateTime.Now, // 發行時間
DateTime.Now.AddHours(4), // 過期時間
false, // 持久化
userData // 用戶數據
);
// 3. 加密並寫入 Cookie
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket)
);
cookie.Domain = ".domain.com"; // 關鍵:設置共享域
Response.Cookies.Add(cookie);
例子:domain.com(主站)、domain.com/subapp(子應用)
原理:Forms 認證加密/解密使用 MachineKey。默認 IsolateApps 導致每個應用生成不同 Key,必須手動指定相同 Key 實現跨應用 Cookie 解密。
例子:domainA.com、domainB.com、domainC.com
| 方案 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| 父域 Cookie | 設置 Cookie Domain 為公共父域 | 簡單、無需額外系統 | 需同根域、安全風險 |
| 集中式 SSO 服務 | CAS/OAuth/OpenID Connect 協議 | 標準化、安全、支持異構系統 | 架構複雜、引入單點故障 |
| Token 重定向傳遞 | 登錄後攜帶 Token 跳轉至目標系統 | 實現靈活、無需共享域 | URL 暴露 Token、需防重放 |
| 後台直連驗證 | 子系統調用 SSO 服務 API 驗證 | 安全、無瀏覽器跳轉 | 增加網絡調用延遲 |
// 登錄系統生成 Token
string token = GenerateSecureToken(userId);
Response.Redirect($"https://appB.com/sso/login?token={token}&returnUrl={targetUrl}");
// 子系統驗證 Token
public ActionResult Login(string token, string returnUrl)
{
var userId = ValidateToken(token);
if (userId > 0)
{
SetLocalAuthCookie(userId);
return Redirect(returnUrl);
}
return RedirectToAction("Login", "Account");
}
SameSite=Lax 或 Strict 防 CSRF根據業務架構複雜度、安全等級、團隊技術棧選擇最適合的 SSO 方案,漸進式演進而非一步到位。