Chrome、Firefox、Edge 和其他浏览器正在根据 IETF 提案 Incrementally Better Cookies 更改其默认行为,以便
- 没有
SameSite
属性的 Cookie 将被视为SameSite=Lax
,这意味着默认行为是将 Cookie 限制为仅第一方上下文。 - 跨站点使用的 Cookie 必须指定
SameSite=None; Secure
才能在第三方上下文中启用包含。
如果您尚未这样做,则应更新第三方 Cookie 的属性,以便它们在未来不会被阻止。
跨站点或第三方 Cookie 的用例
在许多常见的用例和模式中,Cookie 需要在第三方上下文中发送。如果您提供或依赖于这些用例之一,请确保您或提供商正在更新其 Cookie,以保持服务正常运行。
<iframe>
中的内容
在 <iframe>
中显示的不同站点的内容位于第三方上下文中。标准用例包括
- 从其他站点共享的嵌入式内容,例如视频、地图、代码示例和社交帖子。
- 来自外部服务的小部件,例如支付、日历、预订和预订功能。
- 小部件,例如社交按钮或反欺诈服务,它们创建不太明显的
<iframes>
。
Cookie 可以在此处用于(包括但不限于)维护会话状态、存储常规偏好设置、启用统计信息或为现有帐户用户个性化内容。

由于 Web 本身是可组合的,因此 <iframes>
也用于嵌入在顶级或第一方上下文中查看的内容。站点在 iframe 中显示的任何 Cookie 都被视为第三方 Cookie。如果您正在创建希望其他站点嵌入的站点,并且需要 Cookie 才能使其正常工作,则还需要确保这些 Cookie 被标记为跨站点使用,或者您可以在没有 Cookie 的情况下优雅地回退。
跨站点的“不安全”请求
“不安全”在这里听起来可能令人担忧,但它指的是任何可能旨在更改状态的请求。在 Web 上,这主要是 POST 请求。标记为 SameSite=Lax
的 Cookie 在安全顶级导航(例如,单击链接转到其他站点)上发送。但是,使用 POST 向不同站点提交 <form>
之类的操作不包括 Cookie。

此模式用于可以将用户重定向到远程服务以执行某些操作然后再返回的站点,例如,重定向到第三方身份提供商。在用户离开站点之前,会设置一个 Cookie,其中包含一个一次性令牌,期望可以在返回请求时检查此令牌以缓解跨站点请求伪造 (CSRF) 攻击。如果该返回请求通过 POST 传递,则需要将 Cookie 标记为 SameSite=None; Secure
。
远程资源
页面上的任何远程资源(例如来自 <img>
标记或 <script>
标记的资源)可能依赖于随请求发送的 Cookie。常见用例包括跟踪像素和个性化内容。
这也适用于从您的 JavaScript 使用 fetch
或 XMLHttpRequest
发送的请求。如果使用 credentials: 'include'
选项调用 fetch()
,则这些请求很可能包含 Cookie。对于 XMLHttpRequest
,预期的 Cookie 通常由 withCredentials
值 true
指示。这些 Cookie 必须正确标记才能包含在跨站点请求中。
WebView 中的内容
特定于平台的应用程序中的 WebView 由浏览器提供支持。开发人员需要测试影响其应用程序的限制或问题是否也适用于其应用程序的 WebView。
Android 还允许其特定于平台的应用程序使用 CookieManager API 直接设置 Cookie。与使用标头或 JavaScript 设置的 Cookie 一样,如果 Cookie 旨在用于跨站点,请考虑包含 SameSite=None; Secure
。
今天如何实施 SameSite
根据您的需要,将仅在第一方上下文中需要的任何 Cookie 标记为 SameSite=Lax
或 SameSite=Strict
。如果您未标记这些 Cookie,而是依赖默认浏览器行为来处理它们,则它们在不同浏览器中的行为可能不一致,并且可能会为每个 Cookie 触发控制台警告。
Set-Cookie: first_party_var=value; SameSite=Lax
确保将第三方上下文中需要的任何 Cookie 标记为 SameSite=None; Secure
。这两个属性都是必需的。如果您仅指定 None
而没有 Secure
,则 Cookie 将被拒绝。为了解决浏览器实现中的差异,您可能需要使用处理不兼容的客户端中描述的一些缓解策略。
Set-Cookie: third_party_var=value; SameSite=None; Secure
处理不兼容的客户端
由于包含 None
和更新默认行为的这些更改仍然相对较新,因此不同的浏览器以不同的方式处理它们。您可以参考 chromium.org 上的更新页面以获取已知问题的列表,但此列表可能并不详尽。
一种可能的解决方法是以新旧两种样式设置每个 Cookie
Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure
实施较新行为的浏览器会使用 SameSite
值设置 Cookie。不实施新行为的浏览器会忽略该值并设置 3pcookie-legacy
Cookie。在处理包含的 Cookie 时,您的站点应首先检查是否存在新样式的 Cookie,然后回退到旧版 Cookie(如果找不到新 Cookie)。
以下示例展示了如何在 Node.js 中使用 Express 框架及其 cookie-parser 中间件来执行此操作
const express = require('express');
const cp = require('cookie-parser');
const app = express();
app.use(cp());
app.get('/set', (req, res) => {
// Set the new style cookie
res.cookie('3pcookie', 'value', { sameSite: 'none', secure: true });
// And set the same value in the legacy cookie
res.cookie('3pcookie-legacy', 'value', { secure: true });
res.end();
});
app.get('/', (req, res) => {
let cookieVal = null;
if (req.cookies['3pcookie']) {
// check the new style cookie first
cookieVal = req.cookies['3pcookie'];
} else if (req.cookies['3pcookie-legacy']) {
// otherwise fall back to the legacy cookie
cookieVal = req.cookies['3pcookie-legacy'];
}
res.end();
});
app.listen(process.env.PORT);
这种方法需要您执行额外的工作来设置冗余 Cookie,并在设置和读取 Cookie 时进行更改。但是,它应该涵盖所有浏览器,无论其行为如何,并保持第三方 Cookie 的正常运行。
作为替代方案,您可以在发送 Set-Cookie
标头时使用用户代理字符串检测客户端。请参阅不兼容客户端列表,并为您的平台使用适当的用户代理检测库,例如 Node.js 上的 ua-parser-js 库。此方法仅要求您进行一项更改,但用户代理嗅探可能无法捕获所有受影响的用户。
语言、库和框架对 SameSite=None
的支持
大多数语言和库都支持 Cookie 的 SameSite
属性。但是,由于添加 SameSite=None
仍然相对较新,因此您可能需要暂时解决一些标准行为。这些行为记录在 GitHub 上的 SameSite
示例存储库中。
获取帮助
Cookie 在 Web 上随处可见,任何开发团队都很少完全了解其站点在何处设置和使用 Cookie,尤其是在跨站点用例中。当您遇到问题时,这可能是任何人第一次遇到该问题,因此请随时联系
- 在 GitHub 上的
SameSite
示例存储库中提出问题。 - 在 StackOverflow 上的“samesite”标签中提出问题。
- 对于 Chromium 行为的问题,请在 Chromium 问题跟踪器中提出错误。
- 在
SameSite
更新页面上关注 Chrome 的进度。