1. 介绍
本节不具规范性。
Web 应用程序会将数据存储在用户本地计算机上,以便在用户离线时提供功能,并在用户在线时提升性能。这些本地缓存对用户和开发者都带来了显著优势,但同样也存在风险。
用户的数据既敏感又有价值;Web 开发者应当采取合理措施予以保护。可以采取的措施之一是,在存储前加密数据。另一个措施是在数据不再需要时(例如用户退出应用或删除账号时)从用户设备上移除数据。
站点作者可以通过 JavaScript 移除多种存储机制中的数据,但某些机制难以可靠处理。例如,Cookie 可以通过 JavaScript 访问 document.cookie
部分清除,但 HttpOnly Cookie 只能通过 HTTP 响应中的多个 Set-Cookie 头来移除。这需要对主机设置的所有 Cookie
了如指掌,而这通常很复杂。缓存则更难,没有命令式接口可直接操作浏览器的网络缓存。
本文档定义了一种新机制,用以移除这些及其它类型本地存储中的数据,使 Web 开发者能够通过 Clear-Site-Data HTTP 响应头清除用户本地缓存数据。
1.1. 示例
1.1.1. 注销
https://supersecretsocialnetwork.example.com/logout 退出 “超级机密社交网络”,站点作者希望确保本地存储数据因此被移除。
他们可以在响应中发送如下 HTTP 头实现此目的:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.2. 定向清除
https://megacorp.example.com/logout 退出 Megacorp Inc. 站点。Megacorp
有大量子域服务,数量之多导致退出后哪些子域的数据可以安全清除并不清楚。有个选择是全部清除,之后应对各种副作用。然而 Megacorp 的 CEO 曾因误清数据导致在“Irate
Ibexes”游戏中损失大量进度,因此坚决反对对用户造成如此大影响。
不过,开发者知道 “Minus” 应用的数据肯定可以被安全清除。可以在注销落地页中,专门针对该子域发起请求(最好是 CORS 支持且有 CSRF 防护的 POST):
fetch("https://minus.megacorp.example.com/clear-site-data",
{
method: "POST",
mode: "cors",
headers: new Headers({
"CSRF": "[insert sekrit token here]"
})
});
该端点会响应合适的 CORS 头,并对实际请求返回如下响应头:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.3. 保留关键 Cookie
https://ads-are-awesome.example.com/optout 选择退出兴趣定向广告。站点作者希望移除可能包含跟踪信息的 DOM
可访问数据,但又要确保用户刚获得的退出 Cookie 不会被清除。
他们可在响应中发送以下 HTTP 头,仅包含除 "cookies" 以外的所有类型:
Clear-Site-Data: "cache", "storage", "executionContexts"
1.1.4. 紧急开关
他们可以在响应中发送如下 HTTP 头,清除本地所有数据源,从而降低持久型客户端 XSS 风险:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
注意:安装 Service Worker 后,浏览器每隔约 24 小时会向服务器发起一次请求。这种更新 ping 很适合在出现重大事故时发送如上的清除头。[SERVICE-WORKERS]
1.2. 目标
总体目标是让 Web 开发者能更好地控制用户代理为其 origin 本地存储的数据。特别是,开发者应该能够可靠实现以下各点:
-
origin 客户端本地存储机制的数据(如 [INDEXEDDB]、WebSQL、Filesystem、
localStorage及sessionStorage)被清除。 -
origin 主机的 Cookie 被移除 [RFC6265]。
-
为 origin 运行的 Web Worker(专用和共享)被终止。
-
为 origin 注册的 Service Worker 被终止并注销。
-
origin 的资源被移除出用户代理的本地缓存。
-
以上所有操作可传播到对应 HTTPS origin 的 HTTP 版本。
-
上述措施无法被恶意活动文档绕过,也不会因感兴趣数据驻留内存并在清除后重写而失效。
2. 基础设施
本文档采用 ABNF 语法描述格式,具体定义见 [RFC5234],更新见 [RFC7405],并用到了 RFC7230 第7节中定义的 #rule
扩展,以及该文档第 3.2.6 节定义的 quoted-string 规则。
本文档算法及正文多项基础概念依赖于 Infra 标准 [INFRA]。
3. 清除站点数据
开发者可以通过在响应中返回 Clear-Site-Data HTTP 响应头,指示用户代理清除各种类型的相关数据。
3.1. Clear-Site-Data HTTP 响应头字段
Clear-Site-Data HTTP
响应头字段向用户代理发送信号,告知其应移除某一类型集合的所有数据。该头字段的语法如下:
Clear-Site-Data = 1#( quoted-string ) ; #rule 在 RFC 7230 第 7 节定义。
§3.2 Fetch 集成 和 §4.1 解析 描述了 Clear-Site-Data 头的处理方式。
本文档定义了一组可通过该机制清除的基础数据类型。参见下方各自描述。未来版本该头可支持更多数据类型,这些类型必须符合 quoted-string 语法。用户代理在解析头字段时必须忽略未知类型。
- "
cache" -
"
cache" 类型表示服务器希望移除与某个 origin 相关的本地缓存数据,该 origin 来源于特定 response 的 url。这包括 网络缓存,也会移除用户代理实现的其他缓存数据(预渲染页面、脚本缓存、着色器缓存等)。实现细节参见 §4.2.3 清除缓存。
当配合https://example.com/clear的响应发送时,下列头部将导致与https://example.com关联的缓存被清除:Clear-Site-Data: "cache"
注意: 缓存通常不是按 origin 组织的,而是按 URL 及时间戳。这意味着在实际中,按 origin 清除缓存可能需要线性扫描。对于大型缓存,这会成为极其消耗资源的操作。
- "
cookies" -
"
cookies" 类型表示服务器希望移除与特定 origin 相关的 cookies,该 origin 来源于 response 的 url。除 cookies 外,HTTP 身份验证凭据 [RFC7235] 及如 CHANNELID 和 TOKBIND 等 origin 绑定的令牌也会被同时移除。实现细节参见 §4.2.4 清除 cookies。
当配合https://example.com/clear的响应发送时,下列头部会清除与https://example.com关联的 cookies,也会清除同一注册域内任意 origin(如https://www.example.com/和https://more.subdomains.example.com/)的 cookies。Clear-Site-Data: "cookies"
- "
storage" -
"
storage" 类型表示服务器希望移除与特定 origin 关联的本地存储数据, 该 origin 来源于 response 的 url。这包括如 (localStorage、sessionStorage、 [INDEXEDDB]、[WEBDATABASE] 等机制,以及与之相关的如 service worker 注册。实现细节参见 §4.2.5 清除 DOM 可访问存储。
- "
executionContexts" -
"
executionContexts" 类型表示服务器希望使当前渲染该 origin 的执行上下文失效并重新加载, 该 origin 来源于 response 的 url。当配合https://example.com/clear的响应发送时,下列头部会使显示https://example.com的执行上下文失效并重新加载:Clear-Site-Data: "executionContexts"
- "
*" -
"
*"(通配符)伪类型表示其效果等同于指定所有类型。当配合https://example.com/clear的响应发送时,下列头部会导致与https://example.com相关的所有 cookies、缓存、本地存储被清除,且相关执行上下文失效并重新加载:Clear-Site-Data: "*"
注意:通配符具备向前兼容性,即若将来头字段新增更多数据类型,通配符也会涵盖这些类型。
若意图进行广泛清理(即清除该头能知晓下所有数据类型),请务必使用通配符。
请勿将通配符作为上面四种类型的快捷写法,因为该语义未来可能发生变化。
注意: 此处定义的语法与未来对类型过滤机制的扩展兼容。例如,"cookies" 很可能将来需增加防止个别
cookie 被删除的机制。所有类型名用双引号包裹,使我们可无缝从简单字符串分割升级为 JSON 处理而不破坏兼容性。
3.2. Fetch 集成
若从网络获得的 HTTP response 包含 Clear-Site-Data
头,则必须在将响应渲染给用户前完成数据清除。即,在现有 HTTP-network fetch 算法的第 14 步后,执行下列步骤:
-
如果 credentials flag 被设定,且 response 的 头字段列表包含名为
Clear-Site-Data的头,则对 response 执行 §4.2 为响应清除数据。
注意: 该步骤发生在处理 Set-Cookie 头之后。清除 cookies
时会全部清除,这一行为有意如此,因为只移除部分 cookie 可能导致应用处于不确定或脆弱状态。如需精确移除特定 cookies,应通过 Set-Cookie 头设置过期时间实现。
注意: 虽然 fetch 的 credentials flag 目的是限制对 cookies 的修改,Clear-Site-Data 出于一致性,对所有类型施加相同约束。
4. 算法
4.1. 解析
给定一个 response,用户代理可以解析 response 的
Clear-Site-Data 头,返回类型列表,步骤如下:
-
令 types 为空列表。
-
如果 header 为
null或失败,返回空列表。 -
对 header 中每个 type,逐条匹配如下分支:
- `
"cache"` -
将 "cache" 添加入 types。
- `
"cookies"` -
将 "cookies" 添加入 types。
- `
"storage"` -
将 "storage" 添加入 types。
- `
"executionContexts"` -
将 "executionContexts" 添加入 types。
- `
"*"` -
将 "cache"、"cookies"、 "storage"、 以及 "executionContexts" 添加入 types。
- `
-
返回 types。
注意: 当前所有值用上述分支即可覆盖。如后续类型定义更复杂,解析器届时会整体转用 JSON。
4.2. 为 response 清除数据
给定一个 response(response),用户代理可以 为 response 清除站点数据,步骤如下:
-
如果 response 的 url 不是 a priori 认证 URL,则 break。
-
令 types 为 解析 response 的
Clear-Site-Data头 的结果。 -
令 browsing contexts 为 准备为 origin 清除数据 的结果,参数为 origin 和 types。
-
对于 types 中每个 type,逐条执行匹配:
-
匹配分支如下:
-
-
如果 types 包含 "executionContexts",则重新加载 browsing contexts。
注意: 鼓励用户代理为开发者提供调试该清除操作的机制,例如通过控制台消息或时间线条目显示结果。
4.2.1. 准备为 origin 清除数据
给定一个 origin(origin)和类型列表 (types),用户代理可以准备为 origin 清除数据,步骤如下。该算法返回已沙箱化的浏览上下文列表,以防止其用内存中的 JavaScript 变量重建已清除数据。
-
令 sandboxed 为空列表。
-
如果 types 未包含 "
executionContexts",返回 sandboxed。 -
对于用户代理的所有 浏览上下文中的每一个 context:
-
返回 sandboxed。
4.2.2. 重新加载browsing contexts
给定浏览上下文(contexts)列表,用户代理可以按如下方式重新加载浏览上下文:
-
对contexts中的每个context:
4.2.3. 清除origin的缓存
给定一个origin(origin),用户代理可以按如下方式清除origin的缓存:
-
令host为origin的主机。
-
对cache list中的每个entry:
-
从网络缓存中移除entry。
-
-
如果用户代理实现了除纯网络缓存以外的缓存,则必须移除与origin匹配的所有条目。
这里处理的是[RFC7234]中定义的网络缓存,但实际上用户代理缓存远不止如此。供应商特有部分能模糊到什么程度?例如,Chrome 会清除预渲染页面、脚本缓存、WebGL 着色器缓存、WebRTC 各类内容、地址栏建议缓存及各种非内容表示的数据(HSTS/HPKP、SCDH等)。或许[STORAGE]会让这一点更清晰?
4.2.4. 清除origin的 cookies
给定一个origin(origin),用户代理可以按如下方式清除origin的 cookies:
注:我们会清除整个注册域的所有 cookie,因为 cookie 不遵守同源策略,如果只清除特定子域的
cookies,可能导致应用处于未定义状态。比如 accounts.google.com 与 mail.google.com
都有标识用户登录状态的 cookies。
注:此算法假设用户代理已实现cookie 存储(见[RFC6265]5.3节),能按主机检索 cookie 列表并删除单个 cookie。
-
令cookie list为cookie 存储中其
domain属性与registered做域匹配的所有 cookie 集合。 -
对cookie list中的每个cookie:
-
从cookie 存储中移除cookie。
-
-
如果用户代理支持其他类似 cookie 的存储方式,这些也必须针对origin的主机的注册域一起清除。
注:例如用户代理支持 Flash,则通过NPP_ClearSiteData清除本地存储对象。
-
清除与[CHANNELID]和[TOKBIND]绑定的 Channel ID 及 token,这些必须与origin的主机的注册域一致。
同时清除绑定 token/ID 和 HTTP 认证的过程非常模糊。<https://github.com/w3c/webappsec-clear-site-data/issues/2>
4.2.5. 清除origin的 DOM 可访问存储
给定一个origin(origin),用户代理可以按如下方式清除origin的 DOM 可访问存储:
-
对origin的数据库[INDEXEDDB]集合中的每个database:
-
删除database。
-
-
对用户代理中所有ServiceWorker 注册中的每个registration:
-
如果registration的作用域 URL的origin是origin:
-
对registration执行
unregister()。
-
-
-
对用户代理中所有应用缓存的每个appcache:
-
对于任何其他脚本可访问的存储机制,用户代理必须删除与该 origin 相关的所有数据。包括(但不限于):
-
origin 的 WebSQL 数据库[WEBDATABASE]。
-
origin 的文件系统[file-system-api]
-
插件数据(如 Flash 通过NPP_ClearSiteData),
-
5. 安全注意事项
5.1. 清除不彻底
仅清除一种类型的存储有可能会导致应用进入未定义状态。我们通过将所有存储选项一并清除,并要求该 header 只能通过安全连接传递,以一定程度上降低风险。
5.2. Service worker
Clear-Site-Data 头必须只在通过网络获取的响应中生效,而不是用于 service worker 提供的响应。
原因是 service worker 可以为其作用域内的资源请求返回任意响应,包括第三方请求。因此,如果支持 Clear-Site-Data,会赋予其为任意 origin 清除数据的能力。
注意,如果一个请求先发给了 service
worker,未被处理后以service-workers mode = "none"重新通过网络发送,则对应响应为网络响应,可以处理。上一次尝试 service
worker 无关。
另外,service worker 更新属于网络响应,因此不受此限制。这对实现§1.1.4 Kill Switch用例很重要。
6. 隐私注意事项
6.1. Web 开发者控制时机。
如果在适当时机触发,Clear-Site-Data可以通过清除敏感数据提升用户的隐私和安全性。但是,请注意
web 开发者(而不是用户)决定何时触发清除事件。即便假定站点作者无恶意,用户无法保证数据会在某一特定时刻被清除,也无法控制清除的数据类型。
如果用户希望确保站点数据在某一特定时间点被清除,应该依赖其用户代理提供的数据清除功能。
至少,用户代理“应该”([RFC6919]意义上)为用户提供与web开发者相同的功能。理想情况下,还会提供更多,例如清除浏览历史。
6.2. 磁盘上的数据残留。
虽然Clear-Site-Data会触发用户代理的清理操作,但很难保证在清理后磁盘上不再有任何站点数据残留。最终还是靠用户代理确保所有站点痕迹真正被移除,这往往非常困难(比如虚拟内存只是一个例子)。
简言之,大多数用户代理会以“尽力而为”方式实现数据清除,但无法保证彻底擦除。
如果用户希望保证站点数据不留存于磁盘,最佳做法是使用声称不会有意写盘的浏览模式(Chrome 的“无痕”、IE 的“InPrivate”等)。这些模式更能防止数据落盘,但边缘场景下依然有限制。
7. IANA 注意事项
永久消息头字段注册表应更新如下内容:[RFC3864]
7.1. Clear-Site-Data
- 头字段名
- Clear-Site-Data
- 适用协议
- http
- 状态
- 标准
- 作者/修改方
- W3C
- 规范文档
- 本规范(见§3.1 Clear-Site-Data HTTP响应头字段)
8. 致谢
Michal Zalewski 提出了该概念的变体,Mark Knichel 帮助完善了细节。