纯js跨子域名cookie自动判定与动态降级方案:基于hostname智能推导合法domain,运行时实测可写性,按cookie→localstorage→内存map三级降级,读取时聚合清理过期项。

纯 JS 实现跨子域名 Cookie 的自动判定与动态降级,核心在于:**不依赖后端、不硬编码域名、能根据当前 URL 智能推导有效作用域,并在不可写时自动 fallback 到 localStorage 或内存缓存**。关键不是“怎么设 Cookie”,而是“何时设、设在哪、设不成怎么办”。
一、自动推导最宽松但安全的 Cookie domain
不能写 .com 或 .example.com(太宽或无效),也不能写死 .a.example.com(无法覆盖 b.example.com)。正确做法是基于 window.location.hostname 逐级向上尝试:
- 先取完整域名,如
shop.api.example.com - 切分出二级及以上部分:
['shop','api','example','com']
- 从倒数第二段开始拼接:尝试
.api.example.com → 失败则试 <code>.example.com→ 再失败则用空字符串(即仅当前主机) - 验证方式:写一个带该 domain 的测试 Cookie,立即读取;读不到说明 domain 不合法或被浏览器拒绝(如 localhost 或不合规格式)
二、运行时检测 Cookie 是否可写(含第三方限制场景)
现代浏览器(尤其 Safari ITP、Chrome 89+)可能静默拒绝第三方上下文或非安全上下文下的 Cookie 写入。不能只靠 try/catch,要实测:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 生成唯一 key(如
__cookie_test_${Date.now()}_${Math.random().toString(36).substr(2,5)}) - 用目标 domain +
SameSite=Lax+Secure(若 location.protocol === 'https:')写入 - 10ms 后同步读取;读不到 → 标记该 domain + 上下文组合为“不可写”
- 记录结果到内存 Map 中,避免重复探测:
cache.set(`${domain}|${isSecure}`, false)
三、三级降级策略:Cookie → localStorage → 内存对象
每次 setItem 都按优先级链执行,且只写入当前可用的最高级:
-
Level 1(首选):使用已验证有效的 domain 写 Cookie(带
expires和path=/) -
Level 2(兜底持久化):若 Cookie 不可用,写入 localStorage,但加前缀隔离子域(如
__cookie_shop.example.com:token),并监听storage事件做跨标签同步 - Level 3(临时容灾):若 localStorage 也被禁用(如无痕模式),退化为内存 Map 存储,生命周期仅限当前页面实例
四、读取时自动聚合 + 过期清理
get 操作不是简单取值,而是按相同优先级顺序查找,并主动清理过期项:
- 先查 Cookie(解析
document.cookie字符串,注意处理 UTF-8 编码) - 未命中则查 localStorage(匹配前缀 + 检查内置时间戳字段)
- 最后查内存 Map
- 若从低级存储读到值,且该值有明确过期时间(存于 value 内或独立字段),且已过期 → 自动清除,并返回 undefined
- 所有写操作都附带 TTL(毫秒),localStorage 存储结构为:
{v: "xxx", e: 1717023456789}
不复杂但容易忽略:降级不是一次决策,而是每个读/写操作都重新评估上下文(协议、hostname、浏览器能力),配合内存缓存探测结果,才能真正实现“自动”和“动态”。










