User-Agent Client Hints 是 Client Hints API 的新擴充功能,可讓開發人員以符合隱私權保護和人體工學的方式,存取使用者瀏覽器的相關資訊。
開發人員可透過 Client Hints 主動要求使用者的裝置或條件相關資訊,而不需要從 User-Agent (UA) 字串中剖析這些資訊。提供這個替代路徑是最終降低 User-Agent 字串精細程度的第一步。
瞭解如何更新現有功能,以便改為使用 User-Agent 用戶端提示,而非解析 User-Agent 字串。
背景
網路瀏覽器提出要求時,會附上瀏覽器和環境的相關資訊,讓伺服器啟用數據分析功能並自訂回應內容。這個定義早在 1996 年就已定義 (RFC 1945 適用於 HTTP/1.0),您可以在該定義中找到 User-Agent 字串的原始定義,其中包含以下範例:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
這個標頭旨在依重要性順序指定產品 (例如瀏覽器或程式庫) 和註解 (例如版本)。
User-Agent 字串的狀態
在過去的數十年,這個字串累積了許多有關提出要求的用戶端的額外詳細資料 (以及因向下相容性而產生的垃圾資料)。查看 Chrome 目前的 User-Agent 字串,可以發現:
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 字串可能包含足夠的資訊,可用於明確識別個別使用者。
User-Agent 字串可用於許多合法的用途,並為開發人員和網站擁有者提供重要用途。不過,保護使用者隱私,避免使用隱密的追蹤方法,也是非常重要的一環,而預設傳送使用者代理程式資訊,就違背了這個目標。
在 User-Agent 字串方面,也需要改善網路相容性。由於這類資料並未結構化,因此剖析時會造成不必要的複雜性,這通常會導致錯誤和網站相容性問題,進而影響使用者體驗。這些問題也會對較不常見的瀏覽器使用者造成不成比例的影響,因為網站可能無法根據其設定進行測試。
全新推出使用者代理程式用戶端提示
使用者代理程式 Client Hints 可讓您存取相同資訊,但以更能保護隱私權的方式存取,進而讓瀏覽器最終減少使用者代理程式字串的預設值,以便廣播所有資訊。用戶端提示會強制執行一種模式,其中伺服器必須向瀏覽器要求一組有關用戶端的資料 (提示),而瀏覽器會套用自身的政策或使用者設定,決定要傳回哪些資料。也就是說,系統現在會以明確且可稽核的方式管理存取權,而非預設方式公開所有 User-Agent 資訊。開發人員也能享有更簡單的 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 的 User-Agent Client Hints
自 Chrome 89 版起,User-Agent Client Hints 已預設啟用。
根據預設,瀏覽器會傳回瀏覽器品牌、主要 / 主要版本、平台,以及指標 (如果用戶端是行動裝置):
⬆️ 所有要求
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"
User-Agent 回應和要求標頭
⬇️ 回應 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
頁面,並傳送預設的基礎 User-Agent。
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
除了標頭之外,您也可以透過 navigator.userAgentData
在 JavaScript 中存取 User-Agent。您可以分別透過 brands
和 mobile
屬性存取預設的 Sec-CH-UA
、Sec-CH-UA-Mobile
和 Sec-CH-UA-Platform
標頭資訊:
// 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
標頭指定。如要將這個值套用至 User-Agent Client Hints,您需要將提示字串改為小寫,並移除 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.provider
或 img.example.com
DPR: 2
使用 User-Agent Client Hints 的最佳位置
簡單來說,您應該重構解析 User-Agent 標頭或使用任何存取相同資訊的 JavaScript 呼叫 (即 navigator.userAgent
、navigator.appVersion
或 navigator.platform
) 的任何例項,改為使用 User-Agent 用戶端提示。
更進一步來說,您應重新檢查使用 User-Agent 資訊的方式,並盡可能以其他方法取代。通常,您可以利用漸進式增強、功能偵測或回應式設計來達成相同的目標。依賴 User-Agent 資料的主要問題,是您必須在要檢查的資源與其啟用的行為之間,一律維持對應關係。這項維護作業的目的,是確保偵測功能全面且保持最新狀態。
考量上述注意事項後,User-Agent Client Hints 存放區列出了網站的幾種有效用途。
User-Agent 字串會發生什麼事?
我們預計減少現有 User-Agent 字串洩漏的識別資訊量,同時不會對現有網站造成不必要的干擾,以盡量減少網站上的隱密追蹤行為。您現在可以透過 User-Agent Client Hints 瞭解並試驗新功能,無須先變更 User-Agent 字串。
最終,User-Agent 字串中的資訊將減少,以便維持舊版格式,同時只提供與預設提示相同的高階瀏覽器和重要版本資訊。在 Chromium 中,這項變更已延後至至少 2022 年,以便生態系統有更多時間評估新的 User-Agent Client Hints 功能。
您可以透過啟用 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
縮圖由 Unsplash 上的 Sergey Zolkin 提供