简介:本文详细探讨JavaScript环境下子域名Cookie共享的原理、实现方法及安全注意事项,帮助开发者掌握跨子域数据同步技术。
Cookie作为HTTP协议中的客户端存储技术,其作用域由domain和path属性共同决定。默认情况下,浏览器仅向设置Cookie的域名及其子域名发送该Cookie。例如在example.com设置的Cookie,浏览器会自动向api.example.com和static.example.com发送该Cookie。
这种机制源于RFC 6265标准,其中明确规定:当Cookie的domain属性未显式设置时,浏览器将自动设置为当前域名(不含子域名);若显式设置为.example.com(注意开头的点),则允许该Cookie在所有子域名间共享。
现代Web应用常采用分布式架构,将不同功能模块部署在不同子域名下(如auth.example.com处理认证,api.example.com提供接口)。此时需要实现用户认证状态的跨子域共享,避免用户在不同子域间重复登录。
// 设置可在所有子域名共享的Cookiedocument.cookie = "sessionId=abc123; domain=.example.com; path=/; Secure; SameSite=Lax";
关键参数解析:
domain=.example.com:点号开头表示允许所有子域名访问Secure:仅通过HTTPS传输,增强安全性SameSite=Lax:防止CSRF攻击,允许安全导航请求携带Cookie读取时无需特殊处理,浏览器会自动根据当前域名筛选可访问的Cookie:
function getCookie(name) {const value = `; ${document.cookie}`;const parts = value.split(`; ${name}=`);if (parts.length === 2) return parts.pop().split(';').shift();}// 示例:读取跨子域设置的sessionIdconst sessionId = getCookie('sessionId');
当用户在auth.example.com登录后,服务端设置:
// 服务端设置(以Node.js为例)res.cookie('authToken', token, {domain: '.example.com',maxAge: 3600000,httpOnly: true,secure: true});
此后访问app.example.com时,浏览器会自动携带该Cookie,实现无缝登录。
在settings.example.com保存用户偏好:
// 设置全局主题偏好document.cookie = `theme=dark; domain=.example.com; path=/; max-age=${30*24*60*60}`;
其他子域名可通过读取该Cookie应用相同主题设置。
HttpOnly,防止XSS攻击窃取Strict:完全禁止跨站请求携带CookieLax:允许安全导航请求(如链接跳转)None:明确允许跨站请求(需配合Secure使用)原因:未正确设置domain属性或存在拼写错误
解决:
// 错误示例:缺少点号document.cookie = "key=val; domain=example.com"; // 仅限example.com// 正确示例document.cookie = "key=val; domain=.example.com"; // 包含所有子域
当主域名不同时(如example.com与example.org),浏览器安全策略会阻止Cookie共享。此时应考虑:
path=/),应按模块划分在PWA应用中,可通过Service Worker拦截请求,在子域名间共享数据:
// service-worker.jsself.addEventListener('fetch', event => {if (event.request.url.includes('api.example.com')) {const authToken = getCookieFromAnyDomain('authToken');// 添加认证头...}});
| 特性 | HTTP-only Cookie | JWT |
|---|---|---|
| 安全性 | 高(防XSS) | 中(需防范注入) |
| 跨子域共享 | 原生支持 | 需手动处理 |
| 存储位置 | 浏览器 | 客户端/服务端 |
| 撤销难度 | 高(需设置过期) | 中(可存储黑名单) |
建议:敏感操作使用HTTP-only Cookie,非敏感数据可采用JWT
// 使用Puppeteer测试跨子域Cookieconst puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();// 访问子域名A设置Cookieawait page.goto('https://a.example.com');await page.evaluate(() => {document.cookie = "test=123; domain=.example.com";});// 验证子域名B是否能读取await page.goto('https://b.example.com');const cookie = await page.evaluate(() => {return document.cookie;});console.log(cookie.includes('test=123') ? '成功' : '失败');await browser.close();})();
随着Web平台的发展,子域名Cookie共享机制也在演进:
开发者应持续关注W3C标准更新,及时调整实现方案。当前阶段,正确配置的子域名Cookie共享仍是跨域身份验证的主流解决方案。