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
日历微件如下所示:
- 加载占位符:
website.example
请求微件。由于嵌入在website.example
上的calendar.example
widget 无法访问其未分区的 Cookie,因此系统会改为呈现占位符 widget。 - 请求权限:占位符加载,然后调用
document.requestStorageAccess()
以请求storage-access
权限。 - 用户选择授予权限。
- 重新加载 widget:widget 会刷新,这次具有 Cookie 访问权限,最后加载个性化内容。
- 每当用户再次访问嵌入
calendar.example
widget 的网站时,流程都与1、2和 4 步骤完全相同;唯一的简化之处在于,用户无需重新授予访问权限。
此流程效率不高:如果用户已授予存储权限,则初始 iframe 加载、document.requestStorageAccess()
调用和后续重新加载变得没有必要,并且会造成延迟。
使用 HTTP 标头的新流程
新的存储空间访问标头支持更高效地加载嵌入内容,包括非 iframe 资源。
使用存储空间访问权限标头时,如果用户已授予权限,浏览器会自动提取设置了 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 授予存储访问权限,并在用户后续访问时加载 iframe,以便其访问未分区的 Cookie。
使用存储空间访问权限标头后,后续网页访问将触发以下流程:
- 用户再次访问嵌入了
calendar.example
的website.example
。这次提取仍无法像之前那样访问 Cookie。不过,用户之前已授予storage-access
权限,并且提取操作包含Sec-Fetch-Storage-Access: inactive
标头,以指示未分区的 Cookie 访问权限可用但未使用。 calendar.example
服务器会以Activate-Storage-Access: retry; allowed-origin="<origin>"
标头(在本例中,<origin>
为https://website.example
)进行响应,以指明资源提取需要使用具有存储空间访问权限的分区无效 Cookie。- 浏览器会重试请求,这次会包含未分区的 Cookie(为此提取启用
storage-access
权限)。 calendar.example
服务器会返回个性化的 iframe 内容。响应包含Activate-Storage-Access: load
标头,用于指示浏览器应在启用storage-access
权限的情况下加载内容(换句话说,使用未分区的 Cookie 访问权限加载,就像调用了document.requestStorageAccess()
一样)。- 用户代理使用存储空间访问权限加载具有未分区的 Cookie 访问权限的 iframe 内容。完成此步骤后,该微件便可按预期运行。
更新您的解决方案
在以下两种情况下,您可能需要更新代码:
- 您使用的是 SAA,并希望通过标头逻辑实现更好的效果。
- 您有一个验证或逻辑,其取决于服务器上的请求中是否包含
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 开始,您可以注册参与源试用,以便试用“存储空间访问权限标头”功能。如需参与源代码试用,请执行以下操作:
在本地测试
您可以在本地测试“存储空间访问标头”功能,确保您的网站为此次变更做好准备。
请按以下步骤配置您的 Chrome 实例:
- 在
chrome://flags/#storage-access-headers
上启用 Chrome 标志。 - 重启 Chrome 以使更改生效。
互动和分享反馈
如果您有任何反馈或遇到任何问题,可以提交问题。您还可以参阅 GitHub 说明文档,详细了解存储空间访问权限标头。