相关网站集:开发者指南

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

随着 Chrome 弃用第三方 Cookie,其目标是维持关键的网络用例,同时更好地保护用户隐私。例如,许多网站依赖多个网域来提供单一用户体验。组织可能希望针对多个用例维护不同的顶级域名,例如特定国家/地区的域名,或用于托管图片或视频的服务域名。Related Website Set 允许网站跨网域共享数据,但具有特定控件。

概括来讲,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 Set 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 内上下文”是指 iframe 等上下文,其嵌入式网站和顶级网站位于同一 RWS 中。)

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

为了检查它们当前是否有权访问存储空间,嵌入式网站可以使用 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 天内顶级文档中是否存在互动,因为用户已经位于相应网页中。

检查存储空间访问权限

用户对某些浏览器功能(例如相机或地理定位)的访问权限取决于用户授予的权限。Permissions 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.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() 会返回来自同一 Related Website Set 的 true 和跨网站 Cookie,这些 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 或跨源属性,则这些请求将包含 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 Set,请使用从命令行启动的 Chrome 119 或更高版本,并启用 test-third-party-cookie-phaseout Chrome flag

启用 Chrome flag

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

如需使用本地声明的 Related Website Set 启动 Chrome,请创建一个包含属于某个集合的网址的 JSON 对象,并将其传递给 --use-related-website-set

详细了解如何使用 flag 运行 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 Set,您需要在 chrome://flags 中启用 test-third-party-cookie-phaseout,并在命令行中使用 --use-related-website-set 标志启动 Chrome(其中的 JSON 对象包含集合成员的网址)。

--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. related_website_sets.JSON 创建拉取请求 (PR),以便 Chrome 在其中托管 Related Website Set 规范列表,从而提交 Related Website Set。(需要 GitHub 帐号才能创建 PR,并且您需要签署贡献者许可协议 (CLA) 才能为列表做出贡献。)

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

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

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

  • 如果 PR 失败,系统会显示一条错误消息,其中详细说明提交失败的可能原因(示例)。
  • 所有管理集提交的技术检查都在 GitHub 上进行,因此,所有由技术检查导致的提交失败问题都可以在 GitHub 上查看。

企业政策

为了满足企业用户的需求,Chrome 制定了多项企业政策:

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

“用户提示”和“用户手势”

“用户提示”和“用户手势”是不同的含义。对于同一 Related Website Set 中的网站,Chrome 不会向用户显示权限提示,但 Chrome 仍会要求用户与相应网页进行过互动。在授予权限之前,Chrome 需要执行用户手势,也称为“用户互动”或“用户激活”。这是因为根据 Web 平台设计原则,在 Related Website Set 上下文(即 requestStorageAccess())之外使用 Storage Access API 也需要用户手势。

访问其他网站的 Cookie 或存储空间

Related Website Set 不会合并不同网站的存储空间,它只是允许更简单(无提示)的 requestStorageAccess() 调用。Related Website Sets 只会为用户提供更顺畅的 Storage Access API 使用体验,并不会指示用户恢复访问权限后该怎么做。如果 A 和 B 是同一 Related Website Set 中的不同网站,并且 A 嵌入 B,则 B 可以调用 requestStorageAccess() 并获得对第一方存储空间的访问权限,而无需提示用户。Related Website Set 不执行任何跨网站通信。例如,设置 Related Website Set 不会导致属于 B 的 Cookie 开始发送到 A。如果您想共享这些数据,则必须自行共享,例如,将 window.postMessage 从 B iframe 发送到 A 框架。

Related Website Set 不允许在不调用任何 API 的情况下进行隐式未分区 Cookie 访问。默认情况下,跨网站 Cookie 在集合内不可用;Related Website Set 仅允许集合中的网站跳过 Storage Access API 权限提示如果 iframe 想要访问其 Cookie,则必须调用 document.requestStorageAccess(),或者顶级网页可以调用 document.requestStorageAccessFor()

分享反馈

您可以在 GitHub 上提交资源集,并结合使用 Storage Access API 和 requestStorageAccessFor API 来分享您在此流程和遇到的任何问题方面的经验。

如需加入有关 Related Website Set 的讨论,请执行以下操作: