Cookie 的 Domain 屬性控制作用域:
Domain=test1.com → 所有 *.test1.com 可訪問(二級域名共享)test1.com ↔ test2.com)瀏覽器安全策略禁止直接共享
// www.test1.com 設置 Cookie
HttpCookie cookie = new HttpCookie("SSO_Token", "user123");
cookie.Domain = "test1.com"; // 關鍵:設置根域名
cookie.Path = "/";
cookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(cookie);
// bbs.test1.com、api.test1.com 直接讀取 Request.Cookies["SSO_Token"]
條件: 同一根域名,DNS 解析到同一組伺服器或共享機器密鑰(machineKey)。
核心思路: 利用 iframe 或 script src 跨域請求目標域,在目標域內設置 Cookie(同源策略允許頁面向自身域設置 Cookie)。
<%@ Page Language="C#" %>
<html><body>
<script>
// 方式 A: 隱藏 iframe
var frm = document.createElement("iframe");
frm.style.display = "none";
frm.src = "https://www.test2.com/SSO.ashx?token=abc123";
document.body.appendChild(frm);
// 方式 B: script src (需 SSO.ashx 返回 JS)
// var s = document.createElement("script");
// s.src = "https://www.test2.com/SSO.ashx?token=abc123";
// document.body.appendChild(s);
</script>
</body></html>
public class SSO : IHttpHandler {
public void ProcessRequest(HttpContext context) {
string token = context.Request["token"];
HttpCookie cookie = new HttpCookie("SSO_Token", token);
cookie.Domain = "test2.com"; // 設置自身域
cookie.Path = "/";
cookie.Expires = DateTime.Now.AddYears(1);
context.Response.Cookies.Add(cookie);
// 關鍵:P3P 標頭解決 IE iframe 禁用第三方 Cookie
context.Response.AddHeader("P3P", "CP=\"CAO PSA OUR\"");
context.Response.ContentType = "text/plain";
context.Response.Write("OK"); // 或返回 JS: parent.callback('OK');
}
public bool IsReusable => false;
}
protected void Page_Load(object sender, EventArgs e) {
if (Request.Cookies["SSO_Token"] != null)
Response.Write($"Token: {Request.Cookies["SSO_Token"].Value}");
else
Response.Write("Cookie 未找到");
}
C:\Windows\System32\drivers\etc\hosts:
127.0.0.1 www.test1.com 127.0.0.1 www.test2.com
https://www.test1.com/Default.aspx → 自動調用 test2.com 設置 Cookie → 訪問 https://www.test2.com/GetCookie.aspx 驗證IE 6+ 默認阻止第三方 Cookie(iframe 跨域)。P3P (Platform for Privacy Preferences) 聲明隱私政策,滿足 IE 要求方可設置 Cookie。
// 最小可用策略
context.Response.AddHeader("P3P", "CP=\"CAO PSA OUR\"");
// 完整範例
// CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
| 方案 | 原理 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| iframe + P3P | 跨域請求目標域設置 Cookie | 實現簡單、兼容舊瀏覽器 | P3P 廢棄、被廣告攔截器阻塞、安全風險 | 舊系統維護、IE 必須支援 |
| JSONP 回調 | <script src="...?callback=fn"> 返回 JS 設置 Cookie | 無 iframe、可攜帶數據 | 同源腳本注入風險、僅 GET | 簡單數據同步 |
| 共享資料庫/Redis | SessionID 寫入共享存儲,各域讀取 | 安全、可控、支援複雜會話 | 需基礎設施、延遲略高 | 企業級 SSO、微服務架構 |
| OAuth 2.0 / OIDC | 授權碼流程獲取 Token,各域驗證 | 行業標準、安全、解耦 | 實現複雜、需授權服務器 | 新系統、開放平台、跨組織 |
| LocalStorage + postMessage | 主域寫 LocalStorage,子域 postMessage 讀取 | 現代瀏覽器支援、無 Cookie 限制 | 需同源父頁面、無 HTTP 自動攜帶 | 前端重、無後台依賴場景 |
.com、.cn 等公共後綴;必須包含至少一個點(test.com)Secure=true; SameSite=None (NET Core 3.1+/Framework 4.7.2+)<machineKey validationKey="..." decryptionKey="..." /> 保持一致App1_Token、App2_Token)「跨域 Cookie 是歷史妥協產物,現代架構應採用 Token 化認證(JWT/OAuth)+ 共享會話存儲。」—— 理解 iframe+P3P 原理有助於維護舊系統,新專案請直接走標準授權流程。