将网站从依赖于用户代理字符串迁移到 新的用户代理客户端提示。
用户代理 字符串是 大量的被动数字“指纹”收集 呈现方式 而且难以处理然而,还有各种有效的 收集和处理用户代理数据的原因,因此我们需要 找到更好的解决方案。用户代理客户端提示同时提供了两种明确的方法 来声明您需要用户代理数据和方法,以便在 易于使用的格式。
本文将逐步介绍如何审核您对用户代理数据的访问权限,以及 将用户代理字符串的使用迁移到用户代理客户端提示。
审核用户代理数据的收集和使用
与任何形式的数据收集一样,您应始终清楚自己为何 正在收集信息无论您是否 就是了解您在何处以及为什么使用用户代理数据。
如果您不知道是否或在何处使用用户代理数据,请考虑在
使用 navigator.userAgent
的前端代码,以及用于
使用 User-Agent
HTTP 标头。您还应检查前端代码
使用已弃用的功能,例如 navigator.platform
和
navigator.appVersion
。
从功能的角度来看,需要考虑你在代码中的任何位置 录制或处理内容:
- 浏览器名称或版本
- 操作系统名称或版本
- 设备品牌或型号
- CPU 类型、架构或位数(例如 64 位)
您也很可能在使用第三方库或服务 处理用户代理。在这种情况下,请检查它们是否更新为 支持用户代理客户端提示。
是否只使用基本的用户代理数据?
默认的用户代理客户端提示集包括:
Sec-CH-UA
:浏览器名称和主要/重要版本Sec-CH-UA-Mobile
:表示移动设备的布尔值Sec-CH-UA-Platform
:操作系统名称 <ph type="x-smartling-placeholder">- </ph>
- 请注意,规范中对此进行了更新,并将在 Chrome 以及其他基于 Chromium 的浏览器。
建议的用户代理字符串的简化版本也将保留
以向后兼容的方式处理这些基本信息例如,将
Chrome/90.0.4430.85
,则字符串将包含 Chrome/90.0.0.0
。
如果您只检查浏览器名称、主要版本 那么您的代码将继续有效,虽然您可能 以查看弃用警告。
虽然您可以也应该迁移到用户代理客户端提示,但您的旧版 API 代码或资源限制阻止它。模型中 以这种向后兼容的方式输入用户代理字符串 虽然现有代码收到的信息不太详细, 基本功能
策略:按需客户端 JavaScript API
如果您目前使用的是navigator.userAgent
,则应改用
首选 navigator.userAgentData
,然后再回退以解析
用户代理字符串。
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
如果您要检查是移动设备还是桌面设备,请使用布尔值 mobile
:
const isMobile = navigator.userAgentData.mobile;
userAgentData.brands
是包含 brand
和 version
的对象数组
属性,让浏览器能列出与这些属性的兼容性
品牌。您可以直接以数组的形式访问这些数据,也可以使用
some()
调用来检查特定条目是否存在:
function isCompatible(item) {
// In real life you most likely have more complex rules here
return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
// browser reports as compatible
}
如果您需要一个更详细的高熵用户代理值,
您需要指定该属性并在返回的 Promise
中检查结果:
navigator.userAgentData.getHighEntropyValues(['model'])
.then(ua => {
// requested hints available as attributes
const model = ua.model
});
如果您希望从 从服务器端处理到客户端处理JavaScript API 不 需要访问 HTTP 请求标头,因此可在以下位置请求用户代理值:
策略:静态服务器端标头
如果您在服务器上使用 User-Agent
请求标头,并且需要
在您的整个网站中比较一致的数据,这样您就可以
在响应中将所需的客户端提示指定为静态集合。这是一个
一种比较简单的方法,因为您通常只需在一个
位置。例如,如果您已
在此处添加标头、您的托管配置或
为自己的网站使用哪些框架或平台
如果你要转换或自定义回答内容,可以考虑采用此策略 根据用户代理数据提供。
浏览器或其他客户端可能会选择提供不同的默认提示, 最好指定所需的全部信息,即使这些信息通常由 默认值。
例如,Chrome 的当前默认设置表示为:
🇨?️ 响应标头
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
如果您还希望在响应中接收设备模型,那么 发送:
🇨?️ 响应标头
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA
在服务器端进行处理时,您应该首先检查
Sec-CH-UA
标头已发送,然后回退到 User-Agent
标头
如果不可用,则对其进行解析。
策略:将提示委托给跨源请求
如果您要请求的跨域或跨网站子资源要求 用户代理客户端提示需要随其请求发送,您需要 使用权限政策明确指定所需的提示。
例如,假设 https://blog.site
在 Google Cloud 上托管资源,
https://cdn.site
,可返回针对特定设备优化的资源。
https://blog.site
可以请求 Sec-CH-UA-Model
提示,但需要
使用 Permissions-Policy
将其明确委托给 https://cdn.site
。
标头。Clients Hints(客户端提示)中提供了政策控制提示的列表。
基础设施
草稿
🇦?️ 在将提示委托给blog.site
时做出的响应
Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")
⬆️ 请求对 cdn.site
上的子资源包含委托提示
Sec-CH-UA-Model: "Pixel 5"
您可以为多个源指定多个提示,而不仅仅是从 ch-ua
范围指定:
🇨?️ 来自 blog.site
将多个提示委托给多个来源的响应
Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
ch-dpr=(self "https://cdn.site" "https://img.site")
策略:将提示委托给 iframe
跨源 iframe 与跨源资源的工作方式类似,
在 allow
属性中指定要委托的提示。
🇨?️ 来自blog.site
的回复
Accept-CH: Sec-CH-UA-Model
↪️ blog.site
的 HTML
<iframe src="https://widget.site" allow="ch-ua-model"></iframe>
⬆️ 向widget.site
提出请求
Sec-CH-UA-Model: "Pixel 5"
iframe 中的 allow
属性会替换符合以下条件的所有 Accept-CH
标头:
widget.site
可能会自行发送,因此请确保您已指定
iframe 的网站所必不可少。
策略:动态服务器端提示
如果用户体验历程中有特定部分,您需要有更多选择 提示,您可以选择请求这些提示。 而不是以静态方式在整个网站上投放这比 但是如果您已经为每个路由设置了不同的标头 可行。
这里需要注意的一点是,Accept-CH
的每个实例
标头将有效地覆盖现有的该组。因此,如果您动态地
设置标头,那么每个页面都必须请求所需的全部提示。
例如,您可能希望在网站上有一个版块
与用户操作系统保持一致的图标和控件。为此,您可以
此外,还想提取 Sec-CH-UA-Platform-Version
来传送适当的
子资源。
🇨?️ /blog
的响应标头
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
🇨?️ /app
的响应标头
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA
策略:首次请求时需要提供服务器端提示
在某些情况下,您需要的 但这种情况很少见 回顾了原因。
第一个请求实际上表示针对该源的第一个顶级请求 发送的信息。默认提示集包含浏览器 其中包含主要版本、平台和移动设备指示器所以问题 需要问的问题是,页面首次加载时是否需要扩展数据?
有关第一个请求的其他提示,有两个选项。首先,您可以
请使用 Critical-CH
标头。其格式与 Accept-CH
相同
而是告知浏览器,如果第一个请求有
却没有提供关键提示
⬆️ 初始请求
[With default headers]
🇨?️ 响应标头
Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model
🔃? 浏览器使用额外标头重试初始请求
[With default headers + …]
Sec-CH-UA-Model: Pixel 5
这会产生第一个请求的重试开销,但是 实施成本相对较低。发送额外的标头和浏览器 将完成其余工作。
对于需要更多提示的情况 首次网页加载时,Client Hints Reliability 提案 布置一条路线,以在连接级设置中指定提示。这个 使用应用程序层协议 对 TLS 的 Settings(ALPS) 扩展 1.3 以在 HTTP/2 和 HTTP/3 连接上实现提示提前传递。这个 目前仍处于早期阶段,但如果您积极管理自己的 TLS 和 连接设置,那么这正是贡献内容的理想时机。
策略:旧版支持
您的网站上可能存在旧版或第三方代码,具体取决于
navigator.userAgent
,包括用户代理字符串中将被触发
。从长远来看,您应计划改用等效项
navigator.userAgentData
调用,但有临时解决方案。
UA-CH retrofill 是
这个库可让您使用新字符串覆盖 navigator.userAgent
,
根据请求的 navigator.userAgentData
值构建而成。
例如,此代码会生成一个用户代理字符串, 包含“model”提示:
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
生成的字符串将显示 Pixel 5
模型,但仍显示缩减版
92.0.0.0
,因为未请求 uaFullVersion
提示:
Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36
更多支持
如果这些策略未涵盖您的使用案例,请在 privacy-sandbox-dev-support 代码库 ,我们可以一起研究您的问题。
摄影:Ricardo 罗恰 来源:Unsplash