如何在同主域子域间共享access_token等数据(无需URL拼接)
跨子域无URL拼接的认证数据传输方案
方案一:父域Cookie共享
这是跨子域传输认证数据最成熟的方案:
- 登录成功后,在
accounts.example.com将access_token、session_token存入Cookie时,把domain设为.example.com(注意前缀的点),同时配置安全属性降低风险:document.cookie = "access_token=xxx; domain=.example.com; path=/; Secure; HttpOnly; SameSite=Strict"; document.cookie = "session_token=xxx; domain=.example.com; path=/; Secure; HttpOnly; SameSite=Strict"; - 配置完成后,
ABC.example.com页面可直接读取这些Cookie,无需URL拼接,能直接用于API请求头自动携带,或存入localStorage(如果去掉HttpOnly属性,但需做好XSS防护)。
方案二:PostMessage跨页面通信
通过iframe嵌套实现两个子域页面的直接数据传递:
- 在
ABC.example.com页面嵌入隐藏的accounts.example.com中转页面:<iframe id="authFrame" src="https://accounts.example.com/auth-message" style="display:none;"></iframe> - 登录完成后,
accounts.example.com页面通过postMessage发送token:const targetSite = "https://ABC.example.com"; window.parent.postMessage({ type: "AUTH_SUCCESS", accessToken: "xxx", sessionToken: "xxx" }, targetSite); ABC.example.com页面监听message事件,接收并存储token:window.addEventListener("message", (event) => { // 严格验证消息来源,防止恶意攻击 if (event.origin !== "https://accounts.example.com") return; if (event.data.type === "AUTH_SUCCESS") { localStorage.setItem("access_token", event.data.accessToken); localStorage.setItem("session_token", event.data.sessionToken); // 执行后续API调用逻辑 } });
方案三:SharedWorker共享线程中转
适合用户同时打开两个子域页面的场景,通过共享线程中转数据:
- 编写一个放在父域
example.com下的SharedWorker脚本auth-worker.js:const connections = []; self.addEventListener("connect", (e) => { const port = e.ports[0]; connections.push(port); port.addEventListener("message", (msg) => { // 把消息转发给所有其他连接的页面 connections.forEach(conn => { if (conn !== port) conn.postMessage(msg.data); }); }); port.start(); }); accounts.example.com登录成功后,连接Worker并发送token:const worker = new SharedWorker("https://example.com/auth-worker.js"); worker.port.postMessage({ type: "AUTH_TOKENS", accessToken: "xxx", sessionToken: "xxx" }); worker.port.start();ABC.example.com页面连接同一个Worker,接收token并存储:const worker = new SharedWorker("https://example.com/auth-worker.js"); worker.port.addEventListener("message", (msg) => { if (msg.data.type === "AUTH_TOKENS") { localStorage.setItem("access_token", msg.data.accessToken); localStorage.setItem("session_token", msg.data.sessionToken); } }); worker.port.start();
内容的提问来源于stack exchange,提问作者Syed Wasif Simnani
相关产品推荐
相关产品推荐

