存储空间访问权限中的 HTTP 标头支持源试用

Natalia Markoborodova
Natalia Markoborodova

Chrome 将在 130 版中开始一项源试用,以便向 Storage Access API (SAA) 添加 HTTP 标头:Storage Access Headers。新的 Sec-Fetch-Storage-Access 请求标头和 Activate-Storage-Access 响应标头旨在支持非 iframe 资源,并改进依赖于嵌入内容(例如社交媒体 widget、日历和互动工具)的网站的性能和用户体验。

JavaScript 流程及其限制

以前,SAA 需要在每次重新加载时对 document.requestStorageAccess() 进行 JavaScript API 调用,即使用户已授予权限也是如此。虽然此方法很有效,但也存在一些限制:

  • 多次网络往返:该过程通常涉及多次网络请求和页面重新加载,然后嵌入的内容才能完全正常运行。
  • iframe 依赖项:执行 JavaScript 时,强制要求使用 iframe 中的 iframe 或子资源,这会限制开发者的灵活性。

例如,仅使用 JavaScript 在 website.example 上嵌入的 calendar.example 日历微件将如下所示:

  1. 加载占位符website.example 会请求 widget。由于嵌入在 website.example 上的 calendar.example widget 无法访问其未分区的 Cookie,因此系统会改为呈现占位符 widget。
  2. 请求权限:占位符加载,然后调用 document.requestStorageAccess() 以请求 storage-access 权限。
  3. 用户选择授予权限
  4. 重新加载 widget:widget 会刷新,这次具有 Cookie 访问权限,最后加载个性化内容。
  5. 每当用户再次访问嵌入 calendar.example widget 的网站时,流程都与1、24 步骤完全相同;唯一的简化之处在于,用户无需重新授予访问权限。

此流程效率不高:如果用户已授予存储权限,则初始 iframe 加载、document.requestStorageAccess() 调用和后续重新加载变得没有必要,并且会造成延迟。

使用 HTTP 标头的新流程

新的存储访问标头可以更高效地加载嵌入内容,包括非 iframe 资源。

使用 Storage Access Headers 时,如果用户已授予权限,浏览器将自动提取设置了 Sec-Fetch-Storage-Access: inactive 请求标头的资源。开发者无需执行任何操作即可设置请求标头。服务器可以使用 Activate-Storage-Access: retry; allowed-origin=<origin> 标头进行响应,浏览器将使用必要的凭据重试请求。

请求标头

Sec-Fetch-Storage-Access: <access-status>

当用户访问嵌入了跨网站内容的网页时,浏览器会在可能需要凭据(例如 Cookie)的跨网站请求中自动添加 Sec-Fetch-Storage-Access 标头。此标头指示嵌入的 Cookie 访问权限状态。以下是解释其值的方法:

  • none:嵌入代码没有 storage-access 权限,因此无法访问未分区的 Cookie。
  • inactive:嵌入内容具有 storage-access 权限,但尚未选择使用该权限。嵌入没有未分区 Cookie 访问权限。
  • active:嵌入内容具有未分区的 Cookie 访问权限。任何有权访问未分区的 Cookie 的跨源请求都会包含此值。

响应标头

Activate-Storage-Access: <retry-or-reload>

Activate-Storage-Access 标头会指示浏览器使用 Cookie 重试请求,或直接在启用 SAA 的情况下加载资源。标头可以具有以下值:

  • load:指示浏览器向嵌入程序授予对请求资源的未分区 Cookie 的访问权限。
  • retry:服务器响应浏览器应激活存储空间访问权限,然后重试请求。
Activate-Storage-Access: retry; allowed-origin="https://site.example"
Activate-Storage-Access: retry; allowed-origin=*
Activate-Storage-Access: load

支持非 iframe 资源

存储空间访问标头更新为非 iframe 嵌入内容(例如托管在其他网域上的图片)启用了 SAA。以前,当第三方 Cookie 不可用时,任何网络平台 API 都不允许在浏览器中使用凭据加载此类资源。 例如,您的 embedding-site.example 可以请求图片:

   <img src="https://server.example/image"/>

服务器可以返回内容或错误,具体取决于 Cookie 是否可用:

app.get('/image', (req, res) => {
  const headers = req.headers;
  const cookieHeader = headers.cookie;
  // Check if the embed has the necessary cookie access
  if (!cookieHeader || !cookieHeader.includes('foo')) {
  // If the cookie is not present, check if the browser supports Storage Access headers
    if (
      'sec-fetch-storage-access' in headers &&
      headers['sec-fetch-storage-access'] == 'inactive'
    ) {
    // If the browser supports Storage Access API, retry the request with storage access enabled
      res.setHeader('Activate-Storage-Access', 'retry; allowed-origin="https://embedding-site.example"');
    }
    res.status(401).send('No cookie!');
   } else {
    // If the cookie is available, check if the user is authorized to access the image
    if (!check_authorization(cookieHeader)) {
      return res.status(401).send('Unauthorized!');
    }
    // If the user is authorized, respond with the image file
    res.sendFile("path/to/image.jpeg");
  }
});

如果 Cookie 不可用,服务器会检查 Sec-Fetch-Storage-Access 请求标头的值。如果此值设置为 inactive,服务器将返回 Activate-Storage-Access: retry 标头作为响应,指示应使用存储空间访问权限重试该请求。如果没有 Cookie,并且 Sec-Fetch-Storage-Access 标头的值不是 inactive,则图片将无法加载。

HTTP 标头流

通过 HTTP 标头,浏览器可以识别用户何时已向该 widget 授予存储访问权限,并在后续访问期间加载具有未分区 Cookie 访问权限的 iframe。

使用存储访问标头时,后续页面访问将触发以下流程:

  1. 用户再次访问嵌入了 calendar.examplewebsite.example。像以前一样,此次抓取尚无权访问 Cookie。不过,用户之前已授予 storage-access 权限,并且提取操作包含 Sec-Fetch-Storage-Access: inactive 标头,以指示未分区的 Cookie 访问权限可用但未使用。
  2. calendar.example 服务器会返回 Activate-Storage-Access: retry; allowed-origin=<origin> 标头(在本例中,<origin>https://website.example),以表明资源提取需要使用具有存储空间访问权限的未分区 Cookie。
  3. 浏览器会重试请求,这次会包含未分区的 Cookie(为此提取启用 storage-access 权限)。
  4. calendar.example 服务器以个性化 iframe 内容作为响应。响应包含一个 Activate-Storage-Access: load 标头,以指示浏览器应在启用 storage-access 权限的情况下加载内容(换句话说,加载时包含未分区 Cookie 访问权限,就像已调用 document.requestStorageAccess() 一样)。
  5. 用户代理使用存储空间访问权限加载具有未分区的 Cookie 访问权限的 iframe 内容。完成此步骤后,该 widget 可以按预期运行。
一张流程图,展示了存储空间访问标头流程
存储访问标头流程图。

更新您的解决方案

使用存储访问标头功能,您可能需要在以下两种情况下更新代码:

  1. 您使用的是 SAA,并希望通过标头逻辑实现更好的效果。
  2. 您的验证或逻辑取决于服务器上的请求中是否包含 Origin 标头。

实现 SAA 标头逻辑

如需在您的解决方案中使用存储访问标头,您需要更新您的解决方案。假设您是 calendar.example 的所有者。为了让 website.example 能够加载个性化的 calendar.example widget,该 widget 代码必须具有存储空间访问权限。

客户端

现有解决方案无需在客户端上更新任何代码即可使用存储空间访问权限标头功能。请参阅文档,了解如何实现 SAA

服务器端

在服务器端,您可以使用新的标头:

app.get('/cookie-access-endpoint', (req, res) => {
  const storageAccessHeader = req.headers['sec-fetch-storage-access'];

  if (storageAccessHeader === 'inactive') {
    // User needs to grant permission, trigger a prompt
    if (!validate_origin(req.headers.origin)) {
      res.status(401).send(`${req.headers.origin} is not allowed to send` +
          ' credentialed requests to this server.');
      return;
    }
    res.set('Activate-Storage-Access', `retry; allowed-origin=${req.headers.origin}`);
    res.status(401).send('This resource requires storage access. Please grant permission.');
  } else if (storageAccessHeader === 'active') {
    // User has granted permission, proceed with access
    res.set('Activate-Storage-Access', 'load');
    // Include the actual iframe content here
    res.send('This is the content that requires cookie access.');
  } else {
    // Handle other cases (e.g., 'Sec-Fetch-Storage-Access': 'none')
  }
});

查看演示,了解此解决方案在实际中的运作方式。

更新您的来源标头逻辑

借助存储空间访问权限标头,Chrome 会在更多请求中发送 Origin 标头。如果您的服务器端逻辑依赖于仅针对特定类型的请求(例如 CORS 定义的请求)提供 Origin 标头,这可能会影响您的服务器端逻辑。

为避免潜在问题,您需要检查您的服务器端代码:

  • 检查是否存在任何依赖于 Origin 标头的验证或逻辑。
  • 请更新您的代码,以便处理更多情况下出现的 Origin 标头。

主要优势

建议您使用存储空间访问标头来使用 SAA,因为这种方式的性能更高。总体而言,这项变更带来了几项改进:

  • 支持非 iframe 嵌入:为更广泛的资源启用 SAA。
  • 减少网络使用量:减少请求,减少载荷。
  • CPU 使用率更低:JavaScript 处理更少。
  • 改进的用户体验:消除了干扰性的中间加载。

参与源试用

通过源试用,您可以试用新功能,并就其易用性、实用性和效果提供反馈。如需了解详情,请参阅开始试用

从 Chrome 130 开始,您可以注册参与源试用,以试用 Storage Access Headers 功能。 如需参与源试用,请按以下步骤操作:

  1. 前往 Storage Access Headers 源代码试用注册页面
  2. 请按照有关参与原始试用计划的说明操作。

在本地测试

您可以在本地测试存储访问标头功能,以确保您的网站为这一变更做好准备。

请按以下步骤配置您的 Chrome 实例:

  1. chrome://flags/#storage-access-headers 上启用 Chrome 标志。
  2. 重启 Chrome 以使更改生效。

互动和分享反馈

如果您有任何反馈或遇到任何问题,可以提交问题。您还可以参阅 GitHub 说明文档,详细了解 Storage Access Headers。