利用用户代理客户端提示改善用户隐私并提升开发者体验

用户代理客户端提示是对 Client Hints API 的新扩展,可让开发者以可保护隐私且符合人体工程学的方式访问用户浏览器的相关信息。

通过客户端提示,开发者可以主动请求 而无需从用户代理 (UA) 中将其解析出来 字符串。提供这条备选路线是最终 减少用户代理字符串粒度。

了解如何更新依赖于解析 要改用用户代理客户端提示的用户代理字符串。

背景

当网络浏览器发出请求时,它们会包含浏览器的相关信息以及 以便服务器启用分析并自定义响应。 早在 1996 年(适用于 HTTP/1.0 的 RFC 1945)中, 查找用户代理字符串的原始定义,其中包括 示例:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

此标题旨在按照重要程度指定产品(例如 浏览器或库)和注释(如版本)。

用户代理字符串的状态

在为期几十年的时间内,该字符串已累积了各种不同的 发出请求的客户的详细信息(以及由于向后 兼容性)。在查看 Chrome 的当前用户代理时,我们可以看到 字符串:

Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4076.0 Mobile Safari/537.36

上面的字符串包含有关用户操作系统和 设备型号、浏览器的品牌和完整版本,这些都足以 更不用说对其他浏览器进行了许多引用, 因为历史原因。

这些参数与具有完全多样性的可能值的组合 表示 User-Agent 字符串可以包含足够的信息, 对他们进行唯一标识

用户代理字符串支持许多合法的用例, 对开发者和网站所有者来说非常重要不过, 此外,还必须确保用户隐私得到保护,以防被隐蔽跟踪方法, 并默认发送 UA 信息会违背该目标

在用户代理方面, 字符串。它是非结构化的,因此对其进行解析会导致不必要的复杂性, 而这往往会导致用户遇到错误和网站兼容性问题。 这些问题也会严重损害使用不常用的浏览器的用户, 网站可能无法针对其配置进行测试。

全新推出用户代理客户端提示

用户代理客户端提示 让用户能以更注重隐私保护的方式,在 Google Cloud 上 使浏览器最终减少用户代理字符串的默认值 广播所有内容。客户端提示会强制执行 在该模型中,服务器必须请求浏览器提供有关客户端的一系列数据。 (提示),而浏览器会将自己的策略或用户配置应用于 以确定返回哪些数据。也就是说,您不必公开所有 用户代理信息,现在则通过明确的 可审核的方式开发者也受益于更简单的 API - 不再是常规的 表达式!

目前的客户端提示集主要描述浏览器的显示和 连接功能。如需了解详情,请参阅使用客户端提示自动选择资源。 现在我们来快速回顾一下流程

服务器通过标头请求特定的客户端提示:

🇨?️ 服务器的响应

Accept-CH: Viewport-Width, Width

或元标记:

<meta http-equiv="Accept-CH" content="Viewport-Width, Width" />

然后,浏览器可以选择在后续 请求:

⬆️ 后续请求

Viewport-Width: 460
Width: 230

服务器可以选择改变其响应,例如,通过以 适当的分辨率。

用户代理客户端提示可以使用 Sec-CH-UA 扩展属性范围 前缀,可通过 Accept-CH 服务器响应标头指定。所有角色 从铺垫消息开始,然后 然后详细了解完整提案

Chromium 89 中的用户代理客户端提示

自 89 版起,Chrome 中默认启用用户代理客户端提示。

默认情况下,浏览器会返回浏览器品牌、重要版本 / 主要版本、 平台,以及指示客户端为移动设备的指示符:

⬆️ 所有请求

Sec-CH-UA: "Chromium";v="93", "Google Chrome";v="93", " Not;A Brand";v="99"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "macOS"

用户代理响应和请求标头

🇦?️ 响应 Accept-CH
⬆️ 请求标头
⬆️ 请求
示例值
说明
Sec-CH-UA "Chromium";v="84",
"Google Chrome";v="84"
浏览器品牌及其重要版本的列表。
Sec-CH-UA-Mobile ?1 指示浏览器是否在移动设备上使用的布尔值(?1 表示 true)(?0 表示 false)。
Sec-CH-UA-Full-Version "84.0.4143.2" [已弃用]浏览器的完整版本。
Sec-CH-UA-Full-Version-List "Chromium";v="84.0.4143.2",
"Google Chrome";v="84.0.4143.2"
浏览器品牌及完整版本的列表。
Sec-CH-UA-Platform "Android" 设备的平台,通常是操作系统 (OS)。
Sec-CH-UA-Platform-Version "10" 平台或操作系统的版本。
Sec-CH-UA-Arch "arm" 设备的底层架构。虽然这可能与网页显示无关,但该网站可能想要提供默认采用正确格式的下载内容。
Sec-CH-UA-Model "Pixel 3" 设备型号。
Sec-CH-UA-Bitness "64" 底层架构的位数(即以整数或内存地址的位数表示的大小)

示例交换

交换示例如下所示:

⬆️ 浏览器发出初始请求
浏览器正在请求 /downloads 页面,并发送其默认的基本用户代理。

GET /downloads HTTP/1.1
Host: example.site

Sec-CH-UA: "Chromium";v="93", "Google Chrome";v="93", " Not;A Brand";v="99"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Platform: "Android"

🇦?️ 服务器的响应
服务器将发送回网页, 会要求提供完整的浏览器版本和平台。

HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Full-Version-List

⬆️ 后续请求
浏览器会向服务器授予访问 并在后续的所有后续操作中 请求。

GET /downloads/app1 HTTP/1.1
Host: example.site

Sec-CH-UA: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Full-Version-List: " Not A;Brand";v="99.0.0.0", "Chromium";v="98.0.4738.0", "Google Chrome";v="98.0.4738.0"
Sec-CH-UA-Platform: "Android"

JavaScript API

除了标头之外,您还可以在 JavaScript 中通过 navigator.userAgentData。默认的 Sec-CH-UASec-CH-UA-MobileSec-CH-UA-Platform标头信息可通过 brandsmobile 属性:

// Log the brand data
console.log(navigator.userAgentData.brands);

// output
[
  {
    brand: 'Chromium',
    version: '93',
  },
  {
    brand: 'Google Chrome',
    version: '93',
  },
  {
    brand: ' Not;A Brand',
    version: '99',
  },
];

// Log the mobile indicator
console.log(navigator.userAgentData.mobile);

// output
false;

// Log the platform value
console.log(navigator.userAgentData.platform);

// output
"macOS";

其他值可通过 getHighEntropyValues() 调用进行访问。通过 "高熵"指的是信息熵,在其他行业中 字词 - 这些值揭示的用户信息量 。与请求其他标头一样,这取决于浏览器 返回哪些值(如果有)。

// Log the full user-agent data
navigator
  .userAgentData.getHighEntropyValues(
    ["architecture", "model", "bitness", "platformVersion",
     "fullVersionList"])
  .then(ua => { console.log(ua) });

// output
{
   "architecture":"x86",
   "bitness":"64",
   "brands":[
      {
         "brand":" Not A;Brand",
         "version":"99"
      },
      {
         "brand":"Chromium",
         "version":"98"
      },
      {
         "brand":"Google Chrome",
         "version":"98"
      }
   ],
   "fullVersionList":[
      {
         "brand":" Not A;Brand",
         "version":"99.0.0.0"
      },
      {
         "brand":"Chromium",
         "version":"98.0.4738.0"
      },
      {
         "brand":"Google Chrome",
         "version":"98.0.4738.0"
      }
   ],
   "mobile":false,
   "model":"",
   "platformVersion":"12.0.1"
}

演示

您可以在自己的设备上试用标头和 JavaScript API,网址为: user-agent-client-hints.glitch.me.

提示有效期和重置

系统会持续发送通过 Accept-CH 标头指定的提示 浏览器会话期间启动,或直到指定了另一组提示为止。

这意味着,如果服务器发送:

🇨?️ 回应

Accept-CH: Sec-CH-UA-Full-Version-List

然后,浏览器会针对所有请求发送 Sec-CH-UA-Full-Version-List 标头 直到浏览器关闭为止。

⬆️ 后续请求

Sec-CH-UA-Full-Version-List: " Not A;Brand";v="99.0.0.0", "Chromium";v="98.0.4738.0", "Google Chrome";v="98.0.4738.0"

不过,如果收到另一个 Accept-CH 标头,则会完全接收该标头 替换浏览器发送的当前提示。

🇨?️ 回应

Accept-CH: Sec-CH-UA-Bitness

⬆️ 后续请求

Sec-CH-UA-Platform: "64"

之前请求的 Sec-CH-UA-Full-Version-List 不会发送

最好将 Accept-CH 标头视为指定 该网页所需要的提示,即浏览器发送指定的提示 该页面上的所有子资源而提示会一直持续到下 导航,网站不应依赖或假定它们会送达。

您也可以使用该工具有效地清除浏览器发送的所有提示 方法是在响应中发送空白 Accept-CH。建议在任意位置添加此项 用户正在重置偏好设置或退出您的网站。

此模式还与提示通过 <meta http-equiv="Accept-CH" …> 标记之间。请求的提示只会在 而不是通过任何后续导航操作才发出的请求。

提示范围和跨源请求

默认情况下,系统只会针对同源请求发送客户端提示。也就是说, 但如果你要提供关于https://example.com的具体提示, 处于https://downloads.example.com状态,但不会 接收任何提示。

若要允许针对跨源请求提供提示,必须指定每个提示和来源 由 Permissions-Policy 标头标识。要将其应用于用户代理客户端提示,您需要 需要将提示小写并移除 sec- 前缀。例如:

🇨?️ 来自example.com的回复

Accept-CH: Sec-CH-UA-Platform-Version, DPR
Permissions-Policy: ch-ua-platform-version=(self "downloads.example.com"),
                    ch-dpr=(self "cdn.provider" "img.example.com");

⬆️ 请求downloads.example.com

Sec-CH-UA-Platform-Version: "10"

⬆️ 请求cdn.providerimg.example.com

DPR: 2

在哪里使用用户代理客户端提示?

快速答案是,您应该重构任何要解析的实例 用户代理标头中,或者使用任何 JavaScript 调用, 获取相同的信息(即 navigator.userAgentnavigator.appVersion、 或 navigator.platform)来改用用户代理客户端提示。

接下来,您应该重新检查自己对用户代理的使用情况 信息,并尽可能将其替换为其他方法。通常情况下,你可以 通过使用渐进式增强、功能 或自适应设计。 依赖用户代理数据的基本问题是, 保持您所检查的属性与其行为之间的映射 。这是一项维护开销,以确保您的检测 全面更新。

考虑到这些注意事项,用户代理客户端提示代码库列出了一些网站的有效用例

用户代理字符串会怎样?

我们的计划是通过减少 现有用户代理字符串公开的标识信息量 同时不对现有网站造成不当中断。用户代理简介 通过 Client Hints,您现在可以了解和试验新的 功能,然后再对用户代理字符串进行任何更改。

最终, 用户代理字符串中的信息将会减少,因此它可以维持 同时只提供与旧版浏览器相同的高级浏览器 版本信息。在 Chromium 中,此更改已 推迟到至少 2022 年,以便为生态系统提供更多时间 评估新的用户代理客户端提示功能。

您可以通过启用 Chrome 93 中的 about://flags/#reduce-user-agent 标志(注意:此标志之前 在 Chrome 84 - 92 版本中名为 about://flags/#freeze-user-agent)。这将 出于兼容性原因,返回一个包含历史条目的字符串,但带有 净化细节。例如:

Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36

缩略图,作者:Sergey Zolkin 已开启 不启动