運用使用者代理程式用戶端提示,改善使用者隱私和開發人員體驗

User-Agent Client Hints 是 Client Hints API 的新功能,可讓開發人員以保護隱私權且符合人體工學的方式存取使用者瀏覽器的相關資訊。

用戶端提示可讓開發人員主動要求使用者裝置或條件的相關資訊,而不必從使用者代理程式 (UA) 字串中剖析。提供這個替代路徑是最終降低 User-Agent 字串精細程度的第一步。

瞭解如何更新現有功能,必須剖析 User-Agent 字串以改用 User-Agent Client Hints。

背景

網路瀏覽器發出要求時,會包含瀏覽器及其環境的相關資訊,以便伺服器啟用數據分析功能並自訂回應。這在 1996 年 (HTTP/1.0 為 RFC 1945 為 RFC 1945) 中定義了先前的定義,您可以在其中找出User-Agent 字串的原始定義,其中包含範例:

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

此標頭旨在按照重要性,指定產品 (例如瀏覽器或程式庫) 和註解 (例如版本)。

User-Agent 字串的狀態

在介入的「衰減」期間,由於具有回溯相容性的緣故,這個字串會累積有關發出要求之用戶端的各種額外詳細資料 (同時也會累積錯誤)。我們可在查看 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 字串可能包含足夠的資訊,因此能識別個別使用者。如果您在 AmIUnique 測試自己的瀏覽器,就可以查看「您的」User-Agent 字串與「您」的相符程度。產生的「相似度比率」越小,要求越獨特,伺服器就越容易追蹤您。

User-Agent 字串可實現許多合法的用途,並為開發人員和網站擁有者提供重要用途。然而,重要的是確保使用者隱私不受隱密追蹤方法保護,且預設傳送通用 Analytics (分析) 資訊並違反該目標。

回應使用者代理程式字串時,也需要改善網路相容性。它不是結構化,因此剖析時會產生不必要的複雜度,而這通常是造成錯誤和網站相容性問題對使用者造成傷害的原因。由於網站可能無法根據設定進行測試,因此這些問題也可能對較不常見的瀏覽器的使用者造成不成比例的傷害。

全新「使用者代理程式用戶端提示」簡介

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

伺服器可以選擇不同的回應,例如以適當的解析度提供圖片。

User-Agent Client Hints 會透過 Accept-CH 伺服器回應標頭指定 Sec-CH-UA 前置字串,擴大屬性範圍。如需所有詳細資料,請先參閱說明,然後深入查看完整提案

Chromium 89 提供的使用者代理程式用戶端提示

自 89 版起,Chrome 已預設啟用 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 頁面,並傳送預設的基本使用者代理程式。

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。預設的 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 標頭指定每個提示和來源。如要套用至 User-Agent Client Hint,您需要將提示小寫,並移除 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

可以在何處使用「使用者代理程式用戶端提示」?

快速解決方法是重構所有您剖析 User-Agent 標頭,或使用任何存取相同資訊的 JavaScript 呼叫 (例如 navigator.userAgentnavigator.appVersionnavigator.platform) 時,改為使用 User-Agent Client Hints。

進一步檢視這些資訊時,請重新檢查自己是否使用「使用者代理程式」資訊,並盡可能改用其他方法。一般來說,您可以使用漸進式強化、功能偵測或回應式設計來達成相同的目標。依賴 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

Sergey ZolkinUnsplash 上提供的縮圖