存储空间访问权限中的 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 需要在每次重新加载时调用 JavaScript API 来执行 document.requestStorageAccess(),即使用户已授予权限也是如此。虽然此方法很有效,但会带来一些限制:

  • 多次网络往返:在嵌入式内容能够正常运行之前,该过程通常涉及多次网络请求和网页重新加载。
  • iframe 依赖项:JavaScript 执行要求在 iframe 内使用 iframe 或子资源,这限制了开发者的灵活性。

例如,仅使用 JavaScript 嵌入到 website.example 中的 calendar.example 日历 widget 如下所示:

  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 标头的新流程

借助新的 Storage Access Headers,可以更高效地加载嵌入式内容,包括非 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 不可用,则没有 Web 平台 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。

使用 Storage Access 标头时,后续页面访问会触发以下流程:

  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. 用户代理使用 storage-access 权限加载具有未分区 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')
  }
});

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

更新您的 Origin 标头逻辑

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

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

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

主要优点

存储空间访问标头是一种推荐的、性能更高的 SAA 使用方式。总而言之,此变更带来了多项改进:

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

参与源试用

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

您可以注册从 Chrome 130 开始的源试用,尝试使用“存储空间访问权限标头”功能。 如需参与源试用,请执行以下操作:

  1. 前往 Storage Access Headers 来源试用版注册页面
  2. 按照有关参与源试用的说明操作。

在本地测试

您可以在本地测试 Storage Access Headers 功能,以确保您的网站已为此次变更做好准备。

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

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

互动和分享反馈

如果您有任何反馈或遇到任何问题,可以提交问题。您还可以通过 GitHub 说明详细了解存储空间访问标头。