Storage Access API 更新

Storage Access API 允许第三方网页内容请求访问其未分区存储的权限,通常是为了验证用户身份。对于 Safari 和 WebKit,使用 Storage Access API 可以在智能跟踪预防下启用 Cookie 访问。

这篇博文涵盖了 Safari 和 WebKit 中 Storage Access API 的两项更改,以及基于我们过去两年收到的问题而编写的采用指南。

API 功能更改

iOS 和 iPadOS 14.5 以及 macOS Big Sur 11.3 测试版在 Safari 和 WebKit 中包含了 Storage Access API 两项备受期待的更改——每页存储访问和嵌套 iframe 支持。这两项更改都是由 W3C Privacy CG 中的标准流程推动的。

每页存储访问

如果授予 embedee.example 存储访问请求,则在当前第一方网页下,对所有 embedee.example 资源加载的访问权限都会被授予。这包括同级 embedee.example iframe,也包括其他非文档资源。

嵌套 Iframe 可以请求存储访问

想象一个网页嵌入了来自 embedeeOne.example 的跨站 iframe,而该 iframe 又嵌入了来自 embedeeTwo.example 的跨站 iframe,这使得后者成为所谓的嵌套 iframe。从这个版本开始,像 embedeeTwo.example 这样的嵌套 iframe 也被允许请求存储访问。请注意,我们可能在稍后阶段要求第一方通过 Permissions Policy 明确委托此功能。Mozilla 已对此类控制表示兴趣。

如何使用 Storage Access API

为本指南的目的,我们将使用域名 social.example 作为需要 Cookie 访问的嵌入内容,并使用 news.example 作为嵌入 social.example 的第一方网站。

首先,跨站 Iframe 调用 API

Storage Access API 是从跨站或第三方 iframe 内部调用的。如果您的网站是第一方,则无需调用该 API,第一方网站也不能代表第三方调用该 API。

操作指南 #1:作为第一方与用户见面和打招呼

如果您想作为第三方使用 Storage Access API,您首先需要作为第一方执行以下步骤:

  1. 确保您使用的是常规浏览模式,即非私人浏览模式。本指南末尾将介绍私人浏览。
  2. 将用户带到您的域名作为第一方。这是您的网站展示自己并让用户有机会识别您的品牌和域名。识别很重要,因为存储访问提示会显示您嵌入 iframe 的域名。在我们的示例中,这意味着通过导航或弹出窗口将用户带到 URL 栏中显示 social.example 的网页。
  3. 让用户以第一方身份与您的网站进行互动(轻触、点击或使用键盘)。这会告诉浏览器用户确实看过并使用过该网站。注意:在没有用户互动的情况下通过重定向导航到和离开您的网站不计入在内。正式来说,WebKit 的要求是浏览器使用过去 30 天内的用户作为第一方进行互动。通过 Storage Access API 获得存储访问权限算作此类用户互动。在我们的示例中,这意味着让用户轻触/点击 URL 栏中显示 social.example 的网页。
  4. 当您是第一方时设置 Cookie。这会将网站建立为底层 Cookie 政策的“已访问”状态。没有 Cookie 的第三方不能在 Safari 中设置 Cookie,自 2003 年 Safari 1.0 以来从未能这样做。这意味着在您作为第一方设置至少一个 Cookie 之前,您不能作为第三方使用 Storage Access API。在我们的示例中,这意味着在 URL 栏中显示 social.example 的情况下为 social.example 设置 Cookie。

上述要求是为了确保单个网页上可能存在的 50-100 个嵌入式第三方不会都提示用户进行存储访问,只有用户访问并互动过的那些才能进行提示。

操作指南 #2:作为第三方使用 Storage Access API

一旦您让用户以第一方身份与您的网站互动并以第一方身份设置了 Cookie,您就可以开始使用 Storage Access API 了。

  1. 在发布的 Safari 中,即将请求存储访问的跨站 iframe 必须是顶层框架的直接子框架。从 iOS 14.5 和 macOS 11.3(目前处于测试阶段)开始,嵌套 iframe 可以请求存储访问。
  2. 让您的跨站 iframe 在渲染后立即调用 document.hasStorageAccess() 以检查您的状态。注意:不要在用户手势时调用此函数,因为它是异步的,并且会消耗手势。一旦用户手势被消耗,对 document.requestStorageAccess() 的后续调用将失败,因为它不是在处理用户手势时调用的。在我们的示例中,这是 social.example 的 iframe。
  3. 如果 document.hasStorageAccess() 返回 false,则您的 iframe 没有存储访问权限。现在,在表示需要存储访问的 UI 元素上设置事件处理程序,并使该事件处理程序在轻触或点击时调用 document.requestStorageAccess()。这是需要用户手势的 API。在我们的示例中,这是 social.example 的 iframe 调用该 API。
  4. 使用您的跨站 iframe 渲染页面。轻触或点击 iframe 中带有事件处理程序的元素。在我们的示例中,这是使用 social.example 的 iframe 渲染 news.example 的页面,并点击 social.example iframe 文档中的元素。
  5. 如果用户尚未在 news.example 下选择允许 social.example 的存储访问,现在将出现一个提示。在提示中选择“不允许”。提示:暂时不要选择“允许”,因为它会被记住,您需要删除浏览器历史记录才能重置。如果您没有收到提示,则说明您尚未获得作为第一方的用户互动并为 social.example 设置 Cookie(参见操作指南 #1),或者您之前已经选择了“允许”并被记住。
  6. 测试“不允许”情况下的行为。您可以重复进行测试。一直测试,直到您对代码的处理方式满意为止。请注意,当用户在提示中选择“不允许”时,其用户手势会被消耗,并且您的 iframe 中任何需要用户手势的进一步 API 调用都必须让用户再次轻触或点击。我们特意这样设计是为了确保用户的明确拒绝不会触发 iframe 进行进一步的特权 API 调用。此时用户应该能够继续进行其他操作。
  7. 现在再次轻触或点击 iframe,这次在提示中选择“允许”。这应该会在 Promise 解析后开启 Cookie 访问。
  8. 测试“允许”情况下的行为。请注意,当用户在提示中选择“允许”时,其用户手势会保留,并且您的 iframe 中任何需要用户手势的进一步 API 调用都可以直接进行。我们特意这样设计,以便当您获得 Cookie 访问权限并发现用户未处于所需状态(例如未登录)时,您可以打开弹出窗口或将他们导航到您的网站,而无需进一步的用户手势。在我们的示例中,这将是弹出窗口或导航到 social.example
  9. 现在重新加载网页。这将重置您的每页存储访问。轻触或点击 iframe 以触发对 document.requestStorageAccess() 的调用。这应该会不显示提示地开启 Cookie 访问,因为用户已经选择允许并且该选择已被记住。
  10. 最后在私人浏览模式下测试流程。在该模式下,用户必须在您稍后作为第三方请求存储访问的同一选项卡中与您的网站作为第一方进行互动(参见操作指南 #1)。这是因为私人浏览模式为用户打开的每个新选项卡使用单独的临时会话,即这些选项卡的状态是独立的。其余部分应与常规模式相同。