उपयोगकर्ता-एजेंट क्लाइंट हिंट पर माइग्रेट करना

अपनी साइट को यूज़र-एजेंट स्ट्रिंग पर निर्भर रहने से, नए यूज़र-एजेंट क्लाइंट हिंट पर माइग्रेट करने की रणनीतियां.

पब्लिश होने की तारीख: 19 मई, 2021

User-Agent स्ट्रिंग, ब्राउज़र में पैसिव फ़िंगरप्रिंटिंग के लिए एक अहम प्लैटफ़ॉर्म है. साथ ही, इसे प्रोसेस करना मुश्किल होता है. हालांकि, उपयोगकर्ता-एजेंट का डेटा इकट्ठा और प्रोसेस करने के लिए, कई तरह की मान्य वजहें हो सकती हैं. इसलिए, बेहतर समाधान के लिए एक पाथ की ज़रूरत है. उपयोगकर्ता-एजेंट क्लाइंट हिंट, उपयोगकर्ता-एजेंट डेटा की ज़रूरत के बारे में साफ़ तौर पर बताने के साथ-साथ, डेटा को इस्तेमाल में आसान फ़ॉर्मैट में दिखाने के तरीके भी उपलब्ध कराते हैं.

यहां हम आपको उपयोगकर्ता एजेंट के डेटा के ऐक्सेस की ऑडिटिंग करने और उपयोगकर्ता एजेंट स्ट्रिंग के इस्तेमाल को उपयोगकर्ता एजेंट क्लाइंट हिंट पर माइग्रेट करने के बारे में बताएंगे.

Browser Support

  • Chrome: 90.
  • Edge: 90.
  • Firefox: not supported.
  • Safari: not supported.

Source

उपयोगकर्ता-एजेंट के डेटा को इकट्ठा और इस्तेमाल करने की प्रक्रिया का ऑडिट करना

डेटा इकट्ठा करने के किसी भी तरीके के लिए, आपको हमेशा यह समझना चाहिए कि आपको डेटा इकट्ठा क्यों करना है. भले ही, आप कोई कार्रवाई करें या नहीं, सबसे पहले यह समझना ज़रूरी है कि उपयोगकर्ता-एजेंट के डेटा का इस्तेमाल कहां और क्यों किया जा रहा है.

अगर आपको नहीं पता कि उपयोगकर्ता एजेंट के डेटा का इस्तेमाल किया जा रहा है या नहीं या कहां किया जा रहा है, तो navigator.userAgent के इस्तेमाल के लिए अपने फ़्रंटएंड कोड और User-Agent एचटीटीपी हेडर के इस्तेमाल के लिए अपने बैकएंड कोड को खोजें. आपको अपने फ़्रंटएंड कोड में, पहले से बंद की गई सुविधाओं के इस्तेमाल की जांच भी करनी चाहिए. जैसे, navigator.platform और navigator.appVersion.

फ़ंक्शन के हिसाब से, अपने कोड में उन जगहों के बारे में सोचें जहां रिकॉर्डिंग या प्रोसेसिंग की जा रही है:

  • ब्राउज़र का नाम या वर्शन
  • ऑपरेटिंग सिस्टम का नाम या वर्शन
  • डिवाइस का ब्रैंड या मॉडल
  • सीपीयू का टाइप, आर्किटेक्चर या बिट (उदाहरण के लिए, 64-बिट)

ऐसा भी हो सकता है कि आपने उपयोगकर्ता-एजेंट को प्रोसेस करने के लिए, तीसरे पक्ष की लाइब्रेरी या सेवा का इस्तेमाल किया हो. ऐसे में, देखें कि वे उपयोगकर्ता एजेंट क्लाइंट हिंट के साथ काम करने के लिए अपडेट हो रहे हैं या नहीं.

क्या सिर्फ़ उपयोगकर्ता-एजेंट के बुनियादी डेटा का इस्तेमाल किया जा रहा है?

यूज़र-एजेंट क्लाइंट हिंट के डिफ़ॉल्ट सेट में ये शामिल हैं:

  • Sec-CH-UA: ब्राउज़र का नाम और मेजर / अहम वर्शन
  • Sec-CH-UA-Mobile: मोबाइल डिवाइस की जानकारी देने वाली बूलियन वैल्यू
  • Sec-CH-UA-Platform: ऑपरेटिंग सिस्टम का नाम

उपयोगकर्ता-एजेंट स्ट्रिंग के कम किए गए वर्शन में भी यह बुनियादी जानकारी पहले की तरह ही मौजूद रहेगी. उदाहरण के लिए, Chrome/90.0.4430.85 के बजाय, स्ट्रिंग में Chrome/90.0.0.0 शामिल होगा.

अगर आपने ब्राउज़र के नाम, मेजर वर्शन या ऑपरेटिंग सिस्टम के लिए सिर्फ़ उपयोगकर्ता एजेंट स्ट्रिंग की जांच की है, तो आपका कोड काम करता रहेगा. हालांकि, आपको बंद होने की चेतावनियां दिख सकती हैं.

उपयोगकर्ता-एजेंट क्लाइंट के संकेत पर माइग्रेट किया जा सकता है और ऐसा करना चाहिए. हालांकि, हो सकता है कि आपके पास लेगसी कोड या संसाधन से जुड़ी पाबंदियां हों, जिनकी वजह से ऐसा न हो पा रहा हो. उपयोगकर्ता-एजेंट स्ट्रिंग में मौजूद जानकारी को कम करने के लिए, इस तरीके का इस्तेमाल किया गया है, ताकि यह पक्का किया जा सके कि मौजूदा कोड को कम जानकारी मिलती रहे, लेकिन उसके बुनियादी फ़ंक्शन काम करते रहें.

रणनीतियां

यूज़र-एजेंट स्ट्रिंग के इस्तेमाल को यूज़र-एजेंट क्लाइंट हिंट पर माइग्रेट करने के लिए, कई रणनीतियां अपनाई जा सकती हैं.

ऑन-डिमांड क्लाइंट-साइड JavaScript API

अगर navigator.userAgent का इस्तेमाल किया जा रहा है, तो आपको user-agent स्ट्रिंग को पार्स करने से पहले, 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 को एचटीटीपी अनुरोध हेडर का ऐक्सेस ज़रूरत नहीं होती. इसलिए, उपयोगकर्ता-एजेंट की वैल्यू का अनुरोध कभी भी किया जा सकता है.

स्टैटिक सर्वर-साइड हेडर

अगर सर्वर पर 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 हेडर को पार्स करने की सुविधा का इस्तेमाल करें.

अलग-अलग डोमेन से किए जाने वाले अनुरोधों के लिए, हिंट को किसी दूसरे को सौंपना

अगर क्रॉस-ऑरिजिन या क्रॉस-साइट सब-रिसॉर्स का अनुरोध किया जा रहा है, तो आपको अनुमतियों की नीति का इस्तेमाल करके, अपने अनुरोधों के लिए उपयोगकर्ता-एजेंट क्लाइंट के संकेत साफ़ तौर पर बताने होंगे.

उदाहरण के लिए, मान लें कि 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 को सलाह देना

क्रॉस-ऑरिजिन iframes, क्रॉस-ऑरिजिन रिसॉर्स की तरह ही काम करते हैं. हालांकि, आपको allow एट्रिब्यूट में वे हिंट बताने होते हैं जिन्हें आपको अपने-आप लागू होने के लिए देना है.

⬇️ blog.site का जवाब

Accept-CH: Sec-CH-UA-Model

↪️ blog.site के लिए एचटीएमएल

<iframe src="https://widget.site" allow="ch-ua-model"></iframe>

⬆️ widget.site को भेजा गया अनुरोध

Sec-CH-UA-Model: "Pixel 5"

iframe में मौजूद allow एट्रिब्यूट, Accept-CH हेडर को बदल देगा. ऐसा तब होगा, जब widget.site खुद हेडर भेजेगा. इसलिए, पक्का करें कि आपने 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

इससे, पहले अनुरोध पर फिर से कोशिश करने का ओवरहेड होता है. हालांकि, लागू करने की लागत काफ़ी कम होती है. अतिरिक्त हेडर भेजें और बाकी काम ब्राउज़र करेगा.

अगर आपको पेज के पहले लोड होने पर, ज़्यादा संकेत चाहिए, तो क्लाइंट के संकेत की भरोसेमंदता के प्रस्ताव में, कनेक्शन-लेवल की सेटिंग में संकेत देने का तरीका बताया गया है. यह एचटीटीपी/2 और एचटीटीपी/3 कनेक्शन पर, एचटीटीपीएस के लिए, एलान को जल्दी भेजने की सुविधा चालू करने के लिए, TLS 1.3 के ऐप्लिकेशन-लेयर प्रोटोकॉल सेटिंग(एएलपीएस) एक्सटेंशन का इस्तेमाल करता है. यह प्रोजेक्ट अभी शुरुआती दौर में है. हालांकि, अगर आपने अपनी TLS और कनेक्शन सेटिंग को मैनेज किया है, तो अब योगदान देने का सही समय है.

लेगसी सपोर्ट

हो सकता है कि आपकी साइट पर लेगसी या तीसरे पक्ष का ऐसा कोड हो जो navigator.userAgent पर निर्भर हो. इसमें उपयोगकर्ता-एजेंट स्ट्रिंग के ऐसे हिस्से भी शामिल हैं जिन्हें छोटा किया जाएगा. आपको navigator.userAgentData कॉल के बराबर के कॉल पर स्विच करने की योजना बनानी चाहिए. हालांकि, इस बीच एक और तरीका अपनाया जा सकता है.

UA-CH रेट्रोफ़िल एक छोटी लाइब्रेरी है. इसकी मदद से, अनुरोध की गई navigator.userAgentData वैल्यू से बनाई गई नई स्ट्रिंग से navigator.userAgent को बदला जा सकता है.

उदाहरण के लिए, यह कोड एक उपयोगकर्ता-एजेंट स्ट्रिंग जनरेट करता है, जिसमें "मॉडल" हिंट भी शामिल होता है:

import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
  .then(() => { console.log(navigator.userAgent); });

इससे बनी स्ट्रिंग में Pixel 5 मॉडल दिखेगा, लेकिन कम किए गए 92.0.0.0 को भी दिखाया जाएगा, क्योंकि uaFullVersion हिंट का अनुरोध नहीं किया गया था:

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 रेपो में चर्चा शुरू करें. इसके बाद, हम आपकी समस्या को एक साथ हल कर सकते हैं.