多子域系統(a.example.com、b.example.com、api.example.com)需共享登入狀態。核心在於將 Session ID Cookie 的 Domain 設為父域(.example.com),使所有子域請求自動攜帶同一 Session ID。
SessionID (GUID) 為 Key 存儲 Session 資料(InProc/StateServer/SQL/Redis)。ASP.NET_SessionId 攜帶 SessionID。a.example.com),導致跨子域不共享。protected void Session_Start(object sender, EventArgs e) {
// 1. 獲取當前 SessionID
var sessionId = Session.SessionID;
// 2. 重寫 Cookie:同名、同值、Domain 設為父域
var cookie = Response.Cookies["ASP.NET_SessionId"];
cookie.Value = sessionId;
cookie.Domain = ".example.com"; // 關鍵:前綴點號表示父域及所有子域
cookie.Path = "/"; // 確保全站路徑可用
// 可選:cookie.Secure = true; // 僅 HTTPS 傳輸
// 可選:cookie.HttpOnly = true; // 防 XSS 竊取
// 可選:cookie.SameSite = SameSiteMode.Lax; // CSRF 保護
}
a.example.com,開發者工具查看 Cookie:Domain 顯示 .example.com。b.example.com,請求 Header 自動攜帶 ASP.NET_SessionId。b.example.com 代碼讀取 Session["User"] 成功,實現共享。單機 InProc Session 無法跨伺服器共享,必須配置共用存儲:
<sessionState mode="SQLServer"
sqlConnectionString="Data Source=...;Initial Catalog=ASPState;..."
cookieless="false" timeout="20" />
auth.example.com,驗證成功寫入共用 Domain Cookie(如 AuthToken)。AuthToken,驗證有效性並建立本地 Session/Principal。AuthToken (Domain=.example.com) 並通知各子域清理本地 Session。| 現象 | 原因 | 解決 |
|---|---|---|
| 子域仍各自生成新 Session | Cookie Domain 未生效/拼寫錯誤 | 檢查 Response.Cookies["ASP.NET_SessionId"].Domain 輸出;確認瀏覽器接收 |
| Session 資料不同步 | 使用 InProc 模式 | 改用 SQLServer/Redis/StateServer 模式 |
| 登出後仍可存取 | Cookie 未正確刪除 | 設定 cookie.Expires = DateTime.Now.AddDays(-1); Domain=.example.com |
| Chrome 80+ SameSite 阻攔 | 跨站請求不攜帶 Cookie | 設定 SameSite=Lax 或 None+Secure;確保 HTTPS |
Session.RegenerateID() 防 Session Fixation。