相关网站集:开发者指南

Related Website Set (RWS) 是一种网络平台机制,可帮助浏览器了解一系列网域之间的关系。这样一来,浏览器就能够做出关键决策,以启用特定网站功能(例如,是否允许访问跨网站 Cookie)并向用户提供这些信息。

随着 Chrome 弃用第三方 Cookie,其目标是在网络上维护关键用例,同时加强对用户隐私的保护。例如,许多网站依靠多个网域来提供单一用户体验。组织可能需要针对多种应用场景(例如特定国家/地区的域名或用于托管图片或视频的服务域名)保留不同的顶级域名。Related Website Sets 可让网站跨网域共享数据,并且具有特定的控件。

概括来讲,Related Website Set 是一系列域名,其中有一个“设置主域名”和可能有多个“资源集成员”

在以下示例中,primary 列出了主域名,associatedSites 列出了符合相关子集要求的网域。

{
  "primary": "https://primary.com",
  "associatedSites": ["https://associate1.com", "https://associate2.com", "https://associate3.com"]
}

规范的 Related Website Set 列表是一个 JSON 文件格式的可公开查看列表,托管在 Related Website Sets GitHub 代码库中,用作所有集合的可信来源。Chrome 会使用此文件来将其应用于自身的行为。

只有对某个网域拥有管理控制权的用户才能针对该网域创建群组。提交者必须声明每个“集合成员”之间的关系设置为“设置主服务器”。集成员可以包含一系列不同的网域类型,并且必须是基于用例的子集的一部分。

如果您的应用依赖于对同一 Related Website Set 内网站间的跨网站 Cookie(也称为第三方 Cookie)的访问,您可以使用 Storage Access API (SAA)requestStorageAccessFor API 来请求访问这些 Cookie。浏览器可能会以不同的方式处理请求,具体取决于每个网站所属的子集。

如需详细了解提交集合的流程和要求,请参阅提交指南。提交的集合将接受各种技术检查,以验证提交的内容。

当组织需要在不同顶级站点之间共享身份的形式时,Related Website Set 就是一个很好的选择。

Related Website Set 的一些用例如下:

  • 国家/地区自定义。在依靠共享基础架构的同时利用本地化的网站(example.co.uk 可能依赖于由 example.ca 托管的服务)。
  • 服务网域集成。利用用户从不直接与它们互动的服务网域,但同一单位的网站(example-cdn.com)提供服务。
  • 用户内容分离。访问不同域(出于安全原因将用户上传的内容与其他网站内容分隔开来)上的数据,同时允许沙盒化域访问身份验证(和其他)Cookie。如果您投放的是无效的、由用户上传的内容,也可以按照最佳做法,将这些内容安全地托管在同一网域。
  • 嵌入的经过身份验证的内容。支持来自关联媒体资源(仅限在顶级网站上登录的用户的视频、文档或资源)中的嵌入内容。
  • 登录。支持跨关联媒体资源登录。FedCM API 可能也适用于某些用例。
  • Google Cloud Analytics。跨关联媒体资源部署用户转化历程分析和衡量机制,以提高服务质量。

Storage Access API

浏览器支持

  • 119
  • 85
  • 65
  • 11.1

来源

Storage Access API (SAA) 提供了一种方法,让嵌入式跨源内容能够访问通常只有在第一方环境中才能访问的存储空间。

嵌入式资源可以使用 SAA 方法检查它们当前是否有权访问存储空间,以及向用户代理请求访问权限。

如果第三方 Cookie 被屏蔽,但 Related Website Sets (RWS) 已启用,Chrome 将在 RWS 内自动授予权限,否则将向用户显示提示。(“RWS 内环境”是指嵌入式网站和顶级网站位于同一 RWS 中的上下文,例如 iframe。)

查看和请求存储空间访问权限

如需检查自己目前是否有权访问存储空间,嵌入式网站可以使用 Document.hasStorageAccess() 方法。

该方法将返回一个使用布尔值进行解析的 promise,该布尔值指示文档是否已有权访问其 Cookie。如果 iframe 与顶部帧的来源相同,promise 也会返回 true。

如需请求访问跨网站上下文中的 Cookie,可以使用 Document.requestStorageAccess() (rSA)。

requestStorageAccess() API 旨在从 iframe 中调用。该 iframe 必须刚刚收到用户互动(所有浏览器都需要通过用户手势),但 Chrome 还要求:在过去 30 天内的某个时间点,用户已访问过拥有该 iframe 的网站,并已明确地与该网站进行了互动(作为顶级文档,而不是在 iframe 中)。

requestStorageAccess() 会返回一个 promise,可解析是否已授予存储空间访问权限。如果访问因任何原因而遭拒,则 promise 会被拒绝,并注明原因。

Chrome 中的 requestStorageAccessFor

浏览器支持

  • 119
  • 119
  • x
  • x

来源

Storage Access API 只允许嵌入式网站从已接收用户互动的 <iframe> 元素中请求访问存储空间。

这给使用需要 Cookie 的跨网站图片或脚本代码的顶级网站采用 Storage Access API 带来了挑战。

为了解决这个问题,Chrome 采用一种方式,让顶级网站通过 Document.requestStorageAccessFor() (rSAFor) 代表特定源请求存储空间访问权限。

 document.requestStorageAccessFor('https://target.site')

requestStorageAccessFor() API 应由顶级文档调用。该文档还必须是刚刚获得用户互动的。但与 requestStorageAccess() 不同,Chrome 不会检查过去 30 天内某个顶级文档中的互动,因为用户已经位于相应网页中。

检查存储空间访问权限

要使用某些浏览器功能(例如相机或地理定位),必须获得用户授予的权限。权限 API 提供了一种方法来检查访问 API 的权限状态:该 API 是被授予、拒绝的,还是需要某种形式的用户互动(如点击提示或与网页互动)。

您可以使用 navigator.permissions.query() 查询权限状态。

如需检查当前上下文的存储空间访问权限,您需要传入 'storage-access' 字符串:

navigator.permissions.query({name: 'storage-access'})

如需检查指定来源的存储空间访问权限,您需要传入 'top-level-storage-access' 字符串:

navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})

请注意,为了保护嵌入式源站的完整性,此函数只会检查使用 document.requestStorageAccessFor 的顶级文档授予的权限。

根据权限是可以自动授予权限还是需要用户手势,它会返回 promptgranted

每帧模型

rSA 授权按帧应用。rSA 和 rSAFor 授权被视为单独的权限。

每个新框架都需要单独申请存储空间访问权限,并且系统会自动为其授予访问权限。只有第一个请求需要用户手势,而 iframe 发起的任何后续请求(例如导航或子资源)都不需要等待用户手势,因为初始请求会为浏览会话授予这种手势。

刷新、重新加载或以其他方式重新创建 iframe 需要再次请求访问权限。

Cookie 必须同时指定 SameSite=NoneSecure 属性,因为 rSA 仅会为已标记为在跨网站上下文中使用的 Cookie 提供访问权限

具有 SameSite=LaxSameSite=Strict 或没有 SameSite 属性的 Cookie 仅供第一方使用,无论采用 rSA 方法,都不会在跨网站情境中共享。

安全

对于 rSAFor,子资源请求需要资源的跨域资源共享 (CORS) 标头或 crossorigin 属性,以确保明确选择启用。

实现示例

从嵌入式跨源 iframe 请求存储空间访问权限

显示 top-level.site 上的嵌入式网站的示意图
在其他网站的嵌入内容中使用 requestStorageAccess()

检查您是否具有存储空间访问权限

如需检查您是否已拥有存储空间访问权限,请使用 document.hasStorageAccess()

如果 promise 解析为 true,您就可以在跨网站上下文中访问存储空间。如果解析结果为 false,则需要请求存储空间访问权限。

document.hasStorageAccess().then((hasAccess) => {
    if (hasAccess) {
      // You can access storage in this context
    } else {
      // You have to request storage access
    }
});

请求存储空间访问权限

如果您需要请求存储空间访问权限,请先检查存储空间访问权限 navigator.permissions.query({name: 'storage-access'}),确认该权限是需要用户手势,还是能否自动授予。

如果权限为 granted,您可以调用 document.requestStorageAccess(),并且无需用户手势即可成功调用。

如果权限状态为 prompt,您需要在用户手势(例如点击按钮)后启动 document.requestStorageAccess() 调用。

示例:

navigator.permissions.query({name: 'storage-access'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSA();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSA();
    });
    document.body.appendChild(btn);
  }
});

function rSA() {
  if ('requestStorageAccess' in document) {
    document.requestStorageAccess().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

来自框架、导航栏或子资源中的后续请求将自动获得访问跨网站 Cookie 的权限。hasStorageAccess() 会返回 true,并且会针对这些请求发送来自同一 Related Website Set 的跨网站 Cookie,而无需任何其他 JavaScript 调用。

显示在顶级网站上(而不是在嵌入式中)使用 requestStorageAccessFor() 的示意图
针对其他来源在顶级网站上使用 requestStorageAccessFor()

顶级网站可以使用 requestStorageAccessFor() 代表特定源请求存储空间访问权限。

hasStorageAccess() 只会检查调用它的网站是否拥有存储空间访问权限,因此顶级网站可以检查其他来源的权限。

如需了解系统是否会提示用户,或者是否已对指定源授予存储访问权限,请调用 navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})

如果权限为 granted,您可以调用 document.requestStorageAccessFor('https://target.site')。无需用户手势即可启动。

如果权限为 prompt,则您需要在用户手势(例如按钮点击)之后挂钩 document.requestStorageAccessFor('https://target.site') 调用。

示例:

navigator.permissions.query({name:'top-level-storage-access',requestedOrigin: 'https://target.site'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSAFor();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSAFor();
    });
    document.body.appendChild(btn);
  }
});

function rSAFor() {
  if ('requestStorageAccessFor' in document) {
    document.requestStorageAccessFor().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

成功调用 requestStorageAccessFor() 后,如果跨网站请求包含 CORS 或 crossorigin 属性,则跨网站请求将包含 Cookie,因此网站可能需要等待一段时间才能触发请求。

请求必须使用 credentials: 'include' 选项,资源必须包含 crossorigin="use-credentials" 属性。

function checkCookie() {
    fetch('https://related-website-sets.glitch.me/getcookies.json', {
        method: 'GET',
        credentials: 'include'
      })
      .then((response) => response.json())
      .then((json) => {
      // Do something
      });
  }

如何在本地进行测试

前提条件

如需在本地测试 Related Website Sets,请使用从命令行启动的 Chrome 119 或更高版本,并启用 test-third-party-cookie-phaseout Chrome flag

启用 Chrome 标志

若要启用必要的 Chrome 标记,请从地址栏前往 chrome://flags#test-third-party-cookie-phaseout,并将该标记更改为 Enabled。更改标记后,请务必重新启动浏览器。

如需使用本地声明的 Related Website Set 启动 Chrome,请创建一个 JSON 对象(其中包含属于该组的网址),然后将其传递给 --use-related-website-set

详细了解如何运行带有标志的 Chromium

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

示例

若要在本地启用 Related Website Sets,您需要在 chrome://flags 中启用 test-third-party-cookie-phaseout,并通过 --use-related-website-set 标志使用包含属于该资源集成员的网址的 JSON 对象从命令行启动 Chrome。

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

验证您是否有权访问跨网站 Cookie

从受测网站调用 API(rSA 或 rSAFor),并验证对跨网站 Cookie 的访问权限。

如需声明域之间的关系,并指定域所属的子集,请按以下步骤操作:

  1. 确定相关网域,包括将要添加到 Related Website Set 的主网域集主集成员。还要确定每个集合成员属于哪个子集类型
  2. 确保已设置组建要求验证要求
  3. 以正确的 JSON 格式声明 Related Website Set。
  4. 通过创建拉取请求 (PR) 向 Chrome 将托管规范 Related Website Set 列表的related_website_sets.JSON提交 Related Website Set。(您必须拥有 GitHub 账号才能创建 PR,并且需要签署贡献者许可协议 (CLA) 才能参与到列表中。)

创建 PR 后,系统将进行一系列检查,以验证第 2 步中的要求已落实到位。

如果成功,PR 将指示已通过检查。已获批准的 PR 每周(美国东部时间星期二中午 12 点)手动分批合并到规范 Related Website Set 列表中。

如果有任何一项检查失败,提交者将通过 GitHub 上的 PR 失败收到通知。提交者可以修正错误并更新 PR,同时请注意:

  • 当 PR 提交失败时,系统会显示一条错误消息,其中会提供额外信息来说明提交失败的可能原因(示例)。
  • 管理集合提交的所有技术检查都是在 GitHub 上进行的,因此,您可在 GitHub 上查看因技术检查导致的所有提交失败问题。

企业政策

Chrome 制定了两项政策来满足企业用户的需求:

  • 如果系统可能无法与 Related Website Sets 集成,则可以通过 RelatedWebsiteSetsEnabled 政策在所有 Chrome 企业实例中停用 Related Website Sets 功能。
  • 一些企业系统具有仅限内部使用的网站(例如内网),其可注册网域不同于其 Related Website Set 中的网域。如果他们需要将这些网站视为其 Related Website Set 的一部分,而不公开它们(因为这些网域可能属于机密),则可以使用 RelatedWebsiteSetsOverrides 政策扩充或覆盖其公开的 Related Website Set 列表。

Chrome 可解析公共集和企业版集的交集,并将其分为两个集 方式,具体取决于是指定 replacemements 还是 additions

例如,对于公开集 {primary: A, associated: [B, C]}

replacements 组: {primary: C, associated: [D, E]}
企业集合会吸收共同的网站,形成新的网站集合。
结果集: {primary: A, associated: [B]}
{primary: C, associated: [D, E]}
additions 组: {primary: C, associated: [D, E]}
公共资源集和企业版资源集会合并。
生成的集: {primary: C, associated: [A, B, D, E]}

“用户提示”以及“用户手势”

“用户提示”以及“用户手势”是不同的概念Chrome 不会显示 权限提示 针对同一 Related Website Set 中网站的用户,显示 Chrome 仍 需要用户与网页互动过。在授予权限之前 Chrome 要求 用户手势, 也称为“用户互动”或“用户激活”。这是因为 Storage Access API 在 Related Website Set 上下文之外(即 requestStorageAccess())也需要用户手势,因为 Web 平台设计原则

访问其他网站的Cookie 或存储

Related Website Sets 不会合并不同网站的存储,只是允许 更轻松(无提示)的 requestStorageAccess() 调用。相关网站 Set 只会减少用户使用 Storage Access API 时的不便,但不会 指定恢复访问权限后要执行的操作。如果 A 和 B 是不同的网站 在同一个 Related Website Set 中,A 嵌入了 B,B 可以调用 requestStorageAccess(),即可在无提示的情况下使用第一方存储空间 用户。Related Website Set 不执行任何跨网站通信。对于 例如,设置 Related Website Set 不会导致属于 以便开始发送至 A如果您 您必须自行分享,例如通过 将 window.postMessage 从 B iframe 发送到 帧。

Related Website Sets 不允许隐式未分区 Cookie 访问 而无需调用任何 API跨网站 Cookie 不可用 默认;Related Website Set 仅允许该组中的网站 跳过 Storage Access API 权限提示。 如果 iframe 要访问其document.requestStorageAccess() Cookie 或顶级网页可以调用 document.requestStorageAccessFor()

分享反馈

在 GitHub 上提交一组并使用 Storage Access API 和 requestStorageAccessFor API,借此机会分享您对该过程的体验以及遇到的任何问题。

要加入 Related Website Sets 的讨论,请执行以下操作: