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

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

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

इस लेख में, यूज़र-एजेंट डेटा के ऐक्सेस की ऑडिटिंग करने और यूज़र-एजेंट स्ट्रिंग के इस्तेमाल को यूज़र-एजेंट क्लाइंट हिंट पर माइग्रेट करने का तरीका बताया गया है.

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

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

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

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

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

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

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

उपयोगकर्ता एजेंट क्लाइंट के हिंट के डिफ़ॉल्ट सेट में ये शामिल हैं:

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

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

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

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

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

रणनीति: स्टैटिक सर्वर-साइड हेडर

अगर सर्वर पर 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")

रणनीति: iframes को हिंट देना

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

Unsplash पर मौजूद, रिकार्डो रोचा की फ़ोटो