採取以下策略,將網站從仰賴使用者代理程式字串遷移至新的 User-Agent Client Hints。
User-Agent 字串是瀏覽器中重要的被動指紋介面,而且難以處理。然而,收集和處理使用者代理程式資料的方法有很多種,因此您需要的是能找出更好的解決方案。「使用者代理程式用戶端提示」提供一種明確的方式,可讓您宣告需要使用者代理程式資料,以及採用易於使用格式傳回資料的方法。
本文將逐步說明如何稽核您的使用者代理程式資料存取權,並將使用者代理程式字串的使用情形遷移至 User-Agent Client Hints。
稽核使用者代理程式資料的收集與使用方式
和任何形式的資料收集行為一樣,請務必先瞭解收集資料的「原因」。無論您是否打算採取任何動作,第一步都是瞭解您使用使用者代理程式資料的位置和原因。
如果您不知道使用者代理程式資料的用途或於何處,請考慮在前端程式碼搜尋 navigator.userAgent
使用,並透過後端程式碼使用 User-Agent
HTTP 標頭。您也應該檢查前端程式碼,使用已淘汰的功能,例如 navigator.platform
和 navigator.appVersion
。
從函式的角度來看,您可以思考程式碼中錄製或處理的任何位置:
- 瀏覽器名稱或版本
- 作業系統名稱或版本
- 裝置品牌或型號
- CPU 類型、架構或位元程度 (例如 64 位元)
此外,您也可以使用第三方程式庫或服務處理使用者代理程式。在此情況下,請檢查確認其是否正在更新,以支援「User-Agent Client Hints」。
您是否只使用基本使用者代理程式資料?
預設的「使用者代理程式用戶端提示」包括:
Sec-CH-UA
:瀏覽器名稱和主要/重要版本Sec-CH-UA-Mobile
:表示行動裝置的布林值Sec-CH-UA-Platform
:作業系統名稱- 請注意,規格內容已更新,Chrome 和其他以 Chromium 為基礎的瀏覽器很快就會更新。
我們提議的簡化版使用者代理程式字串,也會以回溯相容的方式保留這些基本資訊。舉例來說,字串會包含 Chrome/90.0.0.0
,而非 Chrome/90.0.4430.85
。
如果您只檢查使用者代理程式字串中的瀏覽器名稱、主要版本或作業系統,那麼您的程式碼會繼續運作,但您可能會看到淘汰警告。
雖然您可以且應該遷移至 User-Agent Client Hints,但可能有舊版程式碼或資源限製而無法執行上述操作。以這種回溯相容的方式減少使用者代理程式字串中的資訊,旨在確保雖然現有程式碼接收的資訊較少,但仍應保有基本功能。
策略:隨選用戶端 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
標頭剖析。
策略:將提示委派給跨來源要求
如果要求跨來源或跨網站子資源需要在其要求中傳送 User-Agent Client Hints,則需要使用權限政策明確指定所需的提示。
舉例來說,假設 https://blog.site
託管 https://cdn.site
上的資源,該資源可以傳回針對特定裝置最佳化的資源。https://blog.site
可以要求 Sec-CH-UA-Model
提示,但需要使用 Permissions-Policy
標頭明確委派給 https://cdn.site
。如需政策控管提示清單,請參閱「用戶端提示基礎架構草稿」
⬇️ 回覆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
屬性會覆寫 widget.site
可能傳送的任何 Accept-CH
標頭,因此請確認您已指定 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
這會導致第一次要求重試的負擔,但實作成本相對較低。您只要傳送額外的標頭,瀏覽器就會完成其餘作業。
如果確實需要在第一次載入頁面時提供額外提示,用戶端提示可靠性提案會制定路徑,以便在連線層級設定中指定提示。這樣就能利用 TLS 1.3 的應用程式層通訊協定設定(ALPS) 擴充功能,在 HTTP/2 和 HTTP/3 連線上啟用這種提早傳遞提示。這目前仍在早期階段,但如果您主動管理自己的傳輸層安全標準 (TLS) 和連線設定,這就是決定做出貢獻的理想時機。
策略:舊版支援
網站上可能含有仰賴 navigator.userAgent
的舊版或第三方程式碼,包括會減少的使用者代理程式字串部分。長期而言,您應規劃改用對等的 navigator.userAgentData
呼叫,但有暫時的解決方案。
UA-CH retrofill 是小型程式庫,可讓您將 navigator.userAgent
改為根據要求的 navigator.userAgentData
值建構的新字串。
舉例來說,以下程式碼會產生使用者代理程式字串,額外納入「模型」提示:
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
產生的字串會顯示 Pixel 5
模型,但由於未要求 uaFullVersion
提示,因此仍會顯示縮減的 92.0.0.0
:
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 Rocha,位於 Unsplash 上