← 中文资源

简体中文版本

第三方 Cookie 被禁 — iframe 登录态静默丢失

调试跨站 iframe 随第三方 Cookie 退场而丢失会话,用分区存储测试验证,并迁移到令牌模式。

阅读英文原文

症状

  “沉默”就是签名——没有报错、没有失败请求,只有匿名行为:iframe 刚刚登录成功,随后它的 API 调用不带任何 cookie(网络面板 Cookies 列为空)。两分钟实验完成归因:切换浏览器第三方 Cookie 设置,屏蔽关闭时正常、开启时匿名——依赖关系即被证明。SameSite 列再加第二层:即使不考虑屏蔽,Lax 与 Strict 的 cookie 也从不上跨站 iframe 请求。Safari 与 Chrome 默认屏蔽时复现、关闭屏蔽的配置档正常,是最干净的环境对照。

诊断思路

  先跨配置档对比行为归因于第三方 Cookie 屏蔽;再过滤 iframe 源的请求看 Cookies 列与 SameSite 列,区分“策略不送”与“被屏蔽”;最后审计 Set-Cookie 属性——缺 SameSite=None、缺 Secure、会话限定顶层上下文,都解释这种静默。Storage API 在 iframe 里被分区,早先写下的 localStorage 会话静默读不到,是孪生症状。

根因

  浏览器按顶层站点隔离 cookie:跨站 iframe 里设置的 cookie 属于第三方上下文,现在默认被屏蔽或分区。iframe 因此发出不带会话 cookie 的“已认证”请求,服务器把每个请求都当匿名处理。

修复与验证

  把会话建立移出 iframe 内 cookie:父页用 postMessage 把短时令牌递给 iframe 源(两边都严格校验 origin,绝不用 ‘*’,否则会话修复变成会话泄漏);有可见交互的场景用 Storage Access API 申请未分区访问;重流程干脆重构——顶层弹窗完成认证、postMessage 回传令牌、iframe 消费。确需跨站的 cookie 才设 SameSite=None; Secure。验证时强制开启第三方屏蔽,iframe 流程经令牌交换完成认证、请求携带令牌、Safari 与 Chrome 重载后会话保持。

代码示例

DevTools → Network → iframe requests to widget.example.com
  POST /api/session    Cookies: (none)
// parent (app.example.com):
const iframe = document.querySelector('iframe');
iframe.addEventListener('load', () => {
  iframe.contentWindow.postMessage(
    { type: 'auth', token: shortLivedToken },
    'https://widget.example.com'   // exact origin, never '*'
  );
});

// iframe (widget.example.com):
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://app.example.com') return; // validate
  if (event.data?.type === 'auth') startSession(event.data.token);
});