User-Agent Client Hints 是 Client Hints API 的新擴充功能,可讓開發人員以符合隱私權保護和人體工學的方式,存取使用者瀏覽器的相關資訊。
用戶端提示可讓開發人員主動要求有關使用者的裝置或條件的資訊,而不需要將其剖析出使用者代理程式 (UA) 字串。提供這個替代路徑是最終減少 User-Agent 字串精細程度的第一步。
瞭解如何更新現有的功能,以便改為使用 User-Agent Client Hints,而非解析 User-Agent 字串。
背景
網路瀏覽器提出要求時,會附上瀏覽器和環境的相關資訊,讓伺服器啟用數據分析功能並自訂回應內容。這個定義早在 1996 年就已定義 (RFC 1945 適用於 HTTP/1.0),您可以在該定義中找到「使用者代理程式」字串的原始定義,其中包含以下範例:
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 字串的預設廣播內容。用戶端提示會強制執行一種模式,其中伺服器必須向瀏覽器要求一組有關用戶端的資料 (提示),而瀏覽器會套用自身的政策或使用者設定,決定要傳回哪些資料。也就是說,系統現在會以明確且可稽核的方式管理存取權,而非預設方式公開所有 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 中存取使用者代理程式。您可以分別透過 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
標頭指定。如要將其套用至使用者代理程式用戶端提示,您需要小寫提示,並移除 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 字串中的資訊將減少,以便維持舊版格式,同時只提供與預設提示相同的高階瀏覽器和重要版本資訊。在 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
縮圖由 Unsplash 上的 Sergey Zolkin 提供