禁用第三方 Cookie

2024年 Chrome 全面禁用第三方 Cookie,整理了所有相关内容和应对措施
12月 17日, 2023 · 预计30分钟

跨域(cross-origin) 和 跨站(cross-site)

跨域 cross-origin

同源:协议、主机、端口都一致

cross-origin

(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。

跨站 cross-site

同站:具有相同 eTLD+1,即相同的协议+相同的二级域名

https://a.xxx.comhttps://b.xxx.com 相同的二级域名,是同站

tld+1

cross-site

SameSite

Chrome 51 起,Cookie 新增 SameSite 属性,用来防止 CSRF 攻击 (安全) 和用户追踪 (隐私)。

  • Strict(严格):当设置为 Strict 时,浏览器将只在当前网页的域名与 Cookie 所属的域名完全一致的情况下才发送该 Cookie 。

  • Lax(宽松):当设置为 Lax 时,浏览器将在导航到目标网页的情况下发送 Cookie,但仅限于顶级导航(如点击链接或通过 URL 导航)。在跨域的 POST 请求或通过 iframe 加载的请求中,浏览器将不会发送 Cookie。

  • None(无):当设置为 None 时,浏览器将始终发送 Cookie,无论请求是同站点还是跨站点。但是,要使用 None 值,还需要同时设置 Secure 属性,以确保仅在使用 HTTPS 安全连接时发送 Cookie。

Chrome 80 起,默认会给第三方 Cookie 添加 SameSite=Lax 属性,A 域名跨域请求 B 域名,不会携带 Cookie。 如果要使用三方 Cookie,需显式设置 SameSite=None; Secure

Chrome 118 开始有第三方 Cookie 的警告,2024 年 Q1-Q3 逐步禁用 SameSite=None; Secure,请求时无法读取并携带 SameSite=None;Secure 的 Cookie,响应 Set-Cookie: xxx=xx;SameSite=None;Secure 时也无法写入

影响范围?

测试设置位于 chrome://flags/#test-third-party-cookie-phaseout

  • 前端监控:上报的接口为跨站接口,通过三方 Cookie 来存储一个用户标识;
  • 统一登录:通过统一的跨站 SSO 接口为网站实现单点登录能力,共享用户身份;
  • 广告业务:通过三方 Cookie 存储用户标识,用于进行广告归因或兴趣推荐;
  • CSRF :通过 Cookie 存储 CSRF Token 信息,跨站请求则为三方 Cookie;
  • iframe:通用的聊天、地图等 iframe,通过三方 Cookie 来共享一些状态;

解决方案?

1. 变更携带位置+存储位置

不用 CookieSet-Cookie,改成其他地方,携带位置改到 query、请求头、请求体,存储位置改到 localStorage、sessionStorage、indexDB 等

优点: 自由度高

缺点: 改动较大

2. 服务端代理

例如在 a.com 域名发起请求 b.com/update ,代理将调用改写为 a.com/proxy/b.com/update

优点:略微减少了改造成本

缺点: 改动较大,服务端流量,增加成本

让三方 iframe 嵌入发起的跨站请求的依然可以携带三方 Cookie

解决三方 Cookie 问题的提案中,其实还有一个提案是 SameParty,意味标记同一方的 Cookie。最终采纳的是 Partitioned,不过可以达到差不多的效果。

partitioned

通过设置 Partitioned,就可以将站点选择将 Cookie 存储在由顶级站点分区的单独 Cookie jar 中。比如我们在站点 A 中通过 iframe 嵌入了一个站点 C,正常情况下如果三方 Cookie 被禁用后,C 是无法在 A 站点访问到它的 Cookie 的。如果 C 在它的 Cookie 上指定了 Partitioned 属性,这个 Cookie 将保存在一个特殊的分区 jar 中。 它只会在站点 A 中通过 iframe 嵌入站点 C 时才会生效,浏览器会判定只会在顶级站点为 A 时才发送该 Cookie。当用户访问一个新站点时,例如站点 B,如果也它通过 iframe 嵌入了站点 C,这时在站点 B 下的站点 C 是无法访问到之前在 A 下面设置的那个 Cookie 的。如果用户直接访问站点 C ,一样也是访问不到这个 Cookie 的。

解决同一个公司或组织下不同域名的数据共享能力。

可以将多个站点标记为一方, 例如 taobao.comtmail.com 同样属于阿里, 可以标记为同一方

除了把这个站点在自己的网站下部署一份,有点奇葩的是我们还需要通过 PR 将其 Google 提供的 相关网站集 GitHub 存储库。然后站点可以使用 Storage Access API 通过 requestStorageAccess() 请求访问跨站点 Cookie ,或使用 requestStorageAccessFor() 委托访问。当站点位于同一组内时,浏览器将自动授予访问权限,并且跨站点 Cookie 是可用的。

5. Attribution Reporting API

在不追踪用户跨站活动的情况下,提供跨站点的广告归因、转化分析能力。

使用方式大概是这样的:我们首先需要提供一个用于存储归因报告数据的接口,然后在 HTML a、img 、iframe 等标签上追加 attributionsrc:

<a href="https://shoes.example/landing"
  attributionsrc="http://adtech.example/register-source?..."
  target="_blank">
Click me</a>

<img href="https://advertiser.example/landing"
  attributionsrc="https://adtech.example/register-source?..."/>
<a href="https://shoes.example/landing"
  attributionsrc="http://adtech.example/register-source?..."
  target="_blank">
Click me</a>

<img href="https://advertiser.example/landing"
  attributionsrc="https://adtech.example/register-source?..."/>

或者通过 JavaScript 调用注入 attribution src:

const encodedUrl = encodeURIComponent('https://adtech.example/attribution_source?ad_id=...');
window.open(
  "https://shoes.example/landing",
  "_blank",
  attributionsrc=${encodedUrl});
const encodedUrl = encodeURIComponent('https://adtech.example/attribution_source?ad_id=...');
window.open(
  "https://shoes.example/landing",
  "_blank",
  attributionsrc=${encodedUrl});

6. Topics API

在不依赖三方 Cookie 的情况下由浏览器进行用户的兴趣推断。

通过 Topics API ,浏览器可以根据用户的浏览活动观察并记录用户感兴趣的主题。这些信息只会记录在用户的设备上。然后,Topics API 可以让 API 调用者(例如广告技术平台)访问用户感兴趣的主题,但不会透露有关用户浏览活动的其他信息。

const topics = await document.browsingTopics()
const topics = await document.browsingTopics()

7. Shared Storage API

在保护用户隐私的场景下支持跨站点信息存储和读取。

像其他 JavaScript 存储 API(例如 localStorage 或 indexedDB)一样,我们可以随时写入 Shared Storage ,但区别是我们只能在一个安全的环境(shared storage worklet)中读取共享存储的值。

8. FedCM

提供一种标准化的方式进行用户身份验证和凭据管理。

FedCM(联合凭证管理)是联合身份服务(例如“使用…登录”)的一种隐私保护方法,用户可以通过该方法登录网站,而无需与身份服务或网站共享其个人信息。

附录

  1. SameSite: Lax 下请求
请求类型示例正常情况Lax
链接<a href="..."></a>发送 Cookie发送 Cookie
预加载<link rel="prerender" href="..."/>发送 Cookie发送 Cookie
GET 表单<form method="GET" action="..."> 发送 Cookie发送 Cookie
POST 表单<form method="POST" action="...">发送 Cookie不发送
iframe<iframe src="..."></iframe> 发送 Cookie不发送
AJAX$.get("...") 发送 Cookie不发送
Image<img src="..."> 发送 Cookie不发送

Lax 主要解决 Strict 的易用性问题,用户从第三方页面访问一个已登录的系统时,由于未携带Cookie,总是需要重新登录。但由于现在基本上所有网站都是 SPA + ajax 请求,a 链接跳转携带的 Cookie 一般可以忽视

引用

本文主要为信息整理