← 中文资源

简体中文版本

跨浏览器验证 Cookie 的 SameSite 行为

在测试页故意配置三种 SameSite,观察哪些请求携带 Cookie,证明加固确实拦住了跨站发送。

阅读英文原文

目标

SameSite 各模式在不同请求形态下的表现差异,注定它是一场可以亲手做的黑箱实验:种下三种 Cookie、从第二个源发起探测、读取服务端实际收到了哪几个。实验结果能让加固方案建立在证据而非道听途说之上,也能向团队解释为什么 Lax 是默认、Strict 会把邮件链接点进来的用户登出。

步骤要点

  1. 在站点 A 的 /set 接口用 res.cookie 分别种下 strict、lax、none 三种 SameSite 的 Cookie,先在同源 /echo 请求确认三个都能收到。
  2. 在站点 B 的页面里用 img、iframe、带 credentials 的 fetch 三种跨站子资源请求探测 A,服务端日志应只有 none 到达。
  3. 测顶层导航:从 B 链接到 A 的 GET 请求里 lax 会携带而 strict 不会,这正是 Lax 作为安全默认值的理由。
  4. 把真实会话 Cookie 显式加固为 lax(httpOnly、secure 全开),重跑跨站探测确认会话 Cookie 不再随子资源外泄。
  5. 用自动提交的跨站表单 POST 复现 CSRF 场景,加固后该请求不带会话 Cookie,服务端以未认证拒绝,此类 CSRF 向量关闭。

排错提示

SameSite=None 的 Set-Cookie 被浏览器丢弃是因为 None 必须配 Secure 与 HTTPS,先给探测页配本地证书;各浏览器行为不一致本身就是实验结论,在支持的浏览器矩阵上跑一遍并记录结果,默认选全引擎都尊重的 Lax;Strict 弄坏邮件链接回流的用户体验时,会话 Cookie 保持 Lax,Strict 只留给敏感页面的短时反 CSRF 令牌。

适用边界

SameSite 属于 CSRF 缓解而非认证本身,状态变更的 POST 端点仍需配合 CSRF 令牌;老旧内嵌浏览器完全忽略 SameSite,这类客户端重要的场景要做能力检测或改用令牌 API。

代码示例

Request shape                 | strict | lax | none
------------------------------|--------|-----|-----
same-site fetch               |   Y    |  Y  |  Y
cross-site <img> subresource  |   -    |  -  |  Y
cross-site iframe             |   -    |  -  |  Y
cross-site fetch +credentials |   -    |  -  |  Y
top-level GET navigation      |   -    |  Y  |  Y
cross-site form POST          |   -    |  -  |  Y