SameSite Cookie 说明

了解如何明确标记跨网站 Cookie,以确保您的网站安全无虞。

每个 Cookie 都包含一个键值对,以及一系列用于控制该 Cookie 的使用时间和地点的属性。

通过引入 SameSite 属性(在 RFC6265bis 中定义),您可以声明您的 Cookie 应仅限于第一方环境还是同一网站环境。准确理解此处“网站”的含义会很有帮助。 网站是域名后缀和域名前面一部分的组合。例如,www.web.dev 网域属于 web.dev 网站。

公共后缀列表对此进行了定义,因此它不仅包含 .com 等顶级域名,还包含 github.io 等服务。这样,your-project.github.iomy-project.github.io 就可以算作不同的网站。

在 Cookie 上引入 SameSite 属性提供了三种不同的方法来控制此行为。您可以选择不指定该属性,也可以使用 StrictLax 将 Cookie 限制为仅供同网站请求使用。

如果您将 SameSite 设置为 Strict,则 Cookie 只会在第一方环境中发送。就用户而言,只有当获取 Cookie 的网站与浏览器网址栏中当前显示的网站匹配时,系统才会发送此 Cookie。因此,如果 promo_shown Cookie 设置如下:

Set-Cookie: promo_shown=1; SameSite=Strict

当用户访问您的网站时,Cookie 会按预期随请求一起发送。但是,当通过链接进入您的网站时(例如通过其他网站或朋友发送的电子邮件),在该初始请求中不会发送 Cookie。 如果您的 Cookie 与功能相关的 Cookie 始终在初始导航(例如更改密码或购买)之后,但对 promo_shown 来说限制性太强,这会非常有用。如果您的读者通过链接进入网站,他们希望发送 Cookie,以便应用他们的偏好设置。

这正是 SameSite=Lax 的用武之地,它允许通过这些顶级导航发送 Cookie。我们来回顾一下上面提到的猫咪文章示例,另一个网站引用了你的内容。它们会直接使用您拍摄的猫咪照片,并提供一个指向您的原始文章的链接。

<p>Look at this amazing cat!</p>
<img src="https://blog.example/blog/img/amazing-cat.png" />
<p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>

Cookie 设置如下:

Set-Cookie: promo_shown=1; SameSite=Lax

如果读者查看对方的博客,那么当浏览器请求 amazing-cat.png 时,系统不会发送 Cookie。但是,当读者通过此链接到达您博客上的 cat.html 时,该请求将包含该 Cookie。这使得 Lax 成为影响网站显示的 Cookie 的理想之选,并且 Strict 适用于与用户正在执行的操作相关的 Cookie。

最后,您还可以选择不指定值,而之前需要隐式指明您希望在所有上下文中发送 Cookie。在最新的 RFC6265bis 草案中,我们通过引入新值 SameSite=None 明确了这一点。这意味着,您可以使用 None 明确说明您有意在第三方上下文中发送 Cookie。

三个 Cookie 被标记为“无”“宽松”或“严格”(具体取决于其情境)
将 Cookie 的上下文明确标记为 NoneLaxStrict

不采用 SameSite 的默认行为的更改

虽然 SameSite 属性受到广泛支持,但遗憾的是,它尚未得到开发者的广泛采用。开放式默认设置是随时随地发送 Cookie,这意味着所有用例都适用,但这使得用户容易受到 CSRF 和意外信息泄露。为了鼓励开发者表明自己的意图并为用户提供更安全的体验,IETF 的 Progressively Better Cookies 提案提出了两项主要变更:

  • 没有 SameSite 属性的 Cookie 将被视为 SameSite=Lax
  • 具有 SameSite=None 的 Cookie 还必须指定 Secure,这意味着它们需要一个安全上下文。

从版本 84 开始,Chrome 会实现此默认行为。从 Firefox 69 开始,Firefox 开始对这些组件进行测试,并使其成为未来的默认行为。如需在 Firefox 中测试这些行为,请打开 about:config 并设置 network.cookie.sameSite.laxByDefaultEdge 还计划更改其默认行为。

默认为 SameSite=Lax

未设置任何属性
Set-Cookie: promo_shown=1

如果您发送的 Cookie 未指定任何 SameSite 属性...

已应用默认行为
Set-Cookie: promo_shown=1; SameSite=Lax

浏览器会将该 Cookie 视为已指定 SameSite=Lax

虽然这旨在应用更安全的默认设置,但最好设置一个显式 SameSite 属性,而不是依赖于浏览器为您应用该属性。这样可以明确表示您对 Cookie 的意图,并提高在各种浏览器中获得一致体验的可能性。

SameSite=None”必须是安全的

已遭拒
Set-Cookie: widget_session=abc123; SameSite=None

在不具有 Secure 的情况下设置的 Cookie 会被拒绝

已接受
Set-Cookie: widget_session=abc123; SameSite=None; Secure

您必须确保将 SameSite=NoneSecure 属性配对。

从 Chrome 76 开始,您可以在 about:config 中启用 about://flags/#cookies-without-same-site-must-be-secure,通过设置 network.cookie.sameSite.noneRequiresSecure 来测试此行为。

您需要在设置新 Cookie 和主动刷新现有 Cookie 时应用此设置,即使这些 Cookie 的到期日期已临近也是如此。

这两项变更都向后兼容正确实现了旧版 SameSite 属性的浏览器,或者根本不支持它。通过对这些 Cookie 应用这些更改,可以明确指定 Cookie 的预期用途,而不是依赖于浏览器的默认行为。同样,任何尚未识别 SameSite=None 的客户端都应忽略它并继续执行,就像未设置该属性一样。

如需详细了解如何更新 Cookie 以成功处理这些 SameSite=None 更改以及浏览器行为差异,请参阅后续文章 SameSite Cookie 诀窍

感谢 Lily Chen、Malte Ubl、Mike West、Rob Dodson、Tom Steiner 和 Vivek Sekhar 的贡献和反馈

Pille-Riin Priske 发布的 Cookie 主打图片(由 Unsplash 用户)