跳转到主要内容

category

  • 警告:浏览器正在限制第三方cookie的使用。如果您过去在cookie上设置过SameSite=None,则必须采取其他操作。了解如何准备第三方cookie限制。


注意:此页面是SameSite cookie属性更改系列的一部分,其中包括:

  • 了解Cookie
  • SameSite cookie解释
  • 有计划的相同站点


Chrome、Firefox、Edge和其他公司正在根据IETF的提案“Incrementally Better Cookies”更改其默认行为,以便:

  • 没有SameSite属性的Cookie被视为SameSite=Lax,这意味着默认行为是将Cookie仅限于第一方上下文。
  • 跨站点使用的Cookie必须指定SameSite=None;确保能够包含在第三方环境中。

如果您还没有这样做,您应该更新第三方cookie的属性,这样它们将来就不会被阻止。

浏览器支持

跨站点或第三方cookie的使用案例


有许多常见的用例和模式需要在第三方上下文中发送cookie。如果您提供或依赖其中一个用例,请确保您或提供商正在更新其cookie,以保持服务正常运行。

Content within an <iframe>


<iframe>中显示的来自不同网站的内容位于第三方上下文中。标准用例包括:

  • 从其他网站共享的嵌入内容,如视频、地图、代码示例和社交帖子。
  • 来自外部服务的小工具,如支付、日历、预订和预订功能。
  • 小部件,如社交按钮或反欺诈服务,创建不太明显的<iframes>。

Cookie可用于维护会话状态、存储一般偏好、启用统计信息或为拥有现有帐户的用户个性化内容等。

浏览器窗口的图表,其中嵌入内容的URL与页面的URL不匹配。
如果嵌入的内容与顶级浏览上下文不是来自同一个网站,那么它就是第三方内容。


因为web本质上是可组合的,所以<iframes>也用于嵌入在顶级或第一方上下文中查看的内容。iframe中显示的网站使用的任何cookie都被视为第三方cookie。如果您正在创建希望其他网站嵌入的网站,并且需要Cookie才能使其正常工作,您还需要确保这些网站标记为跨网站使用,或者您可以在没有Cookie的情况下优雅地退出。

跨站点的“不安全”请求


“不安全”在这里听起来可能令人担忧,但它指的是任何可能旨在改变状态的请求。在网络上,这主要是POST请求。标记为SameSite=Lax的Cookie是在安全的顶级导航上发送的,比如点击链接转到另一个网站。然而,类似于使用POST向不同网站提交<form>的内容不包括cookie。

请求从一个页面移动到另一个页面的示意图。


如果传入请求使用“安全”方法,则页面会发送cookie。


此模式用于可以将用户重定向到远程服务以在返回之前执行某些操作的站点,例如,重定向到第三方身份提供程序。在用户离开网站之前,会设置一个cookie,其中包含一个一次性令牌,期望可以在返回的请求中检查该令牌,以减轻跨网站请求伪造(CSRF)攻击。如果返回请求是通过POST发出的,则需要将cookie标记为 SameSite=None; Secure

远程资源


页面上的任何远程资源,如<img>标签或<script>标签,都可能依赖于随请求一起发送的cookie。常见的用例包括跟踪像素和个性化内容。

这也适用于使用fetch或XMLHttpRequest从JavaScript发送的请求。如果使用credentials:'include'选项调用fetch(),那么这些请求很可能包含cookie。对于XMLHttpRequest,预期的cookie通常由withCredentials值fo true表示。这些cookie必须适当标记,才能包含在跨站点请求中。

WebView中的内容


特定平台应用程序中的WebView由浏览器提供支持。开发人员需要测试影响应用程序的限制或问题是否也适用于应用程序的WebViews。

Android还允许其特定平台的应用程序直接使用Cookie管理器API设置Cookie。与使用头文件或JavaScript设置的cookie一样,请考虑包含SameSite=None;如果它们用于跨站点使用,则是安全的。

今天如何实现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遗留cookie。当处理包含的cookie时,您的网站应首先检查是否存在新样式的cookie,如果找不到新的cookie,则返回到旧的cookie。

下面的例子展示了如何在Node.js中使用Express框架及其cookie解析器中间件来实现这一点:

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解析器js库。这种方法只需要进行一次更改,但用户代理嗅探可能无法捕获所有受影响的用户。

要点:无论您选择哪种选项,我们强烈建议您添加一种使用传统cookie记录流量水平的方法,并在流量下降超过您网站可接受的阈值时删除您的解决方法。


Support for SameSite=None in languages, libraries, and frameworks


大多数语言和库都支持Cookie的SameSite属性。然而,由于SameSite=None的添加还是相对较新的,因此您现在可能需要解决一些标准行为。这些行为记录在GitHub上的SameSite示例存储库中。

获得帮助


Cookie在网络上随处可见,任何开发团队都很少完全了解其网站的设置和使用位置,尤其是在跨网站使用情况下。当你遇到问题时,这可能是第一次有人遇到它,所以不要犹豫,要联系:

在GitHub上的SameSite示例存储库中提出问题。
在StackOverflow上的“samesite”标记中提问。
对于Chromium的行为问题,请在Chromium问题跟踪器中提出一个错误。
在SameSite更新页面上关注Chrome的进展。

文章链接