שיפור פרטיות המשתמשים וחוויית המפתחים באמצעות User-Agent Client Hints

רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש הם תוספת חדשה ל-Client Hints API, שמאפשרת למפתחים לגשת למידע על הדפדפן של המשתמש באופן ארגונומי ושומרת על הפרטיות.

הנחיות ללקוח מאפשרות למפתחים לבקש באופן פעיל מידע על המכשיר או התנאים של המשתמש, במקום לנתח אותו מהמחרוזת User-Agent‏ (UA). הוספת המסלול החלופי הזה היא השלב הראשון בדרך להפחתת רמת הפירוט של מחרוזת User-Agent.

איך מעדכנים את הפונקציונליות הקיימת שמסתמכת על ניתוח המחרוזת של User-Agent, כדי להשתמש במקום זאת באותות לסוכן המשתמש (UA-CH)

רקע

כשדפדפני אינטרנט שולחים בקשות, הן כוללות מידע על הדפדפן ועל הסביבה שלו, כדי שהשרתים יוכלו להפעיל ניתוח נתונים ולהתאים אישית את התגובה. ההגדרה הזו נקבעה כבר בשנת 1996 (RFC 1945 עבור HTTP/1.0), שם אפשר למצוא את ההגדרה המקורית של מחרוזת User-Agent, שכוללת דוגמה:

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

הכותרת הזו נועדה לציין, לפי סדר החשיבות, את המוצר (למשל דפדפן או ספרייה) ואת ההערה (למשל גרסה).

המצב של מחרוזת סוכן המשתמש

במהלך העשור שחלף, המחרוזת הזו צברה מגוון פרטים נוספים על הלקוח ששלח את הבקשה (וגם נתונים מיותרים, בגלל תאימות לאחור). אפשר לראות את זה כשבודקים את המחרוזת הנוכחית של סוכן המשתמש ב-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 להכיל מספיק מידע כדי לאפשר זיהוי ייחודי של משתמשים ספציפיים.

מחרוזת User-Agent מאפשרת תרחישים לדוגמה רבים ותפקידה חשוב למפתחים ולבעלי אתרים. עם זאת, חשוב גם להגן על פרטיות המשתמשים מפני שיטות מעקב סמויות, ושליחת פרטי UA כברירת מחדל מנוגדת למטרה הזו.

בנוסף, יש צורך לשפר את התאימות לאינטרנט בכל הנוגע למחרוזת User-Agent. הוא לא מובנה, ולכן ניתוחו גורם לסבך מיותר, שפעמים רבות גורם לבאגים ולבעיות תאימות לאתר שגורמות נזק למשתמשים. הבעיות האלה פוגעות באופן לא פרופורציונלי גם במשתמשים בדפדפנים פחות נפוצים, כי יכול להיות שהאתרים לא עברו בדיקה בהתאם להגדרות שלהם.

חדש: רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש

איסוף אותות בצד הלקוח של סוכן משתמש מאפשר גישה לאותו מידע, אבל באופן שמגן יותר על הפרטיות. כך, הדפדפנים יוכלו לצמצם בסופו של דבר את השידור של כל המידע במחרוזת ברירת המחדל של סוכן המשתמש. רמזים ללקוח אוכפים מודל שבו השרת צריך לבקש מהדפדפן קבוצת נתונים על הלקוח (הרמזים), והדפדפן מחיל את כללי המדיניות או את הגדרות המשתמש שלו כדי לקבוע אילו נתונים יחזרו. המשמעות היא שבמקום לחשוף את כל המידע של סוכן המשתמש כברירת מחדל, הגישה מנוהלת עכשיו באופן מפורש וניתנת לבקרה. מפתחים נהנים גם מ-API פשוט יותר – בלי ביטויים רגולריים!

הקבוצה הנוכחית של הטיפים ללקוח מתארת בעיקר את יכולות התצוגה והחיבור של הדפדפן. אפשר לקרוא את הפרטים במאמר בחירת משאבים באופן אוטומטי באמצעות רמזים ללקוח, אבל ריכזנו כאן סיכום קצר של התהליך.

השרת מבקש רמזים ספציפיים ללקוח באמצעות כותרת:

⬇️ תגובה מהשרת

Accept-CH: Viewport-Width, Width

או מטא תג:

<meta http-equiv="Accept-CH" content="Viewport-Width, Width" />

לאחר מכן, הדפדפן יכול לבחור לשלוח בחזרה את הכותרות הבאות בבקשות הבאות:

⬆️ בקשה חוזרת

Viewport-Width: 460
Width: 230

השרת יכול לבחור לשנות את התשובות שלו, למשל על ידי הצגת תמונות ברזולוציה מתאימה.

רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש מרחיבים את טווח המאפיינים באמצעות הקידומת Sec-CH-UA, שאפשר לציין אותה דרך כותרת התגובה Accept-CH של השרת. כדי לקבל את כל הפרטים, כדאי להתחיל בהסבר ואז להמשיך לקרוא את הצעה המלאה.

רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש מ-Chromium 89

רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש מופעלים כברירת מחדל ב-Chrome מגרסה 89 ואילך.

כברירת מחדל, הדפדפן מחזיר את המותג של הדפדפן, את הגרסה המשמעותית או הראשית, את הפלטפורמה ואת האינדיקטור אם הלקוח הוא מכשיר נייד:

⬆️ כל הבקשות

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"

כותרות של תגובה ובקשה של סוכן משתמש

⬇️ כותרת תגובה 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

בנוסף לכותרות, אפשר לגשת ל-User-Agent ב-JavaScript גם דרך navigator.userAgentData. אפשר לגשת למידע של כותרות ברירת המחדל Sec-CH-UA,‏ Sec-CH-UA-Mobile ו-Sec-CH-UA-Platform באמצעות המאפיינים brands ו-mobile, בהתאמה:

// 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" …>. ההצעות המבוקשות יישלחו רק לבקשות שהדף ייזום, ולא לניווטים הבאים.

היקף הטיפים ובקשות מ-origin שונה

כברירת מחדל, אותות בצד הלקוח (Client Hints) יישלחו רק בבקשות מאותו מקור. כלומר, אם מבקשים טיפים ספציפיים ב-https://example.com, אבל המשאבים שרוצים לבצע להם אופטימיזציה נמצאים ב-https://downloads.example.com, לא יתקבלו טיפים לגבי המשאבים האלה.

כדי לאפשר להוסיף רמזים לבקשות ממקורות שונים, צריך לציין כל רמז ומקור באמצעות כותרת Permissions-Policy. כדי להחיל את זה על רמז על הלקוח (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.provider או ל-img.example.com

DPR: 2

איפה משתמשים ברמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש?

התשובה המהירה היא שצריך לבצע רפגורמציה של כל המופעים שבהם אתם מנתחים את הכותרת User-Agent או משתמשים בקריאות JavaScript שגולשות לאותו מידע (כלומר navigator.userAgent,‏ navigator.appVersion או navigator.platform) כדי להשתמש במקום זאת ב-User-Agent Client Hints.

כדאי גם לבדוק מחדש את השימוש שלכם בפרטים של User-Agent ולהחליף אותם בשיטות אחרות כשהדבר אפשרי. לרוב אפשר להשיג את אותו היעד באמצעות שיפור הדרגתי, זיהוי תכונות או עיצוב רספונסיבי. הבעיה הבסיסית בשימוש בנתוני User-Agent היא שצריך תמיד לשמור על מיפוי בין הנכס שבודקים לבין ההתנהגות שהוא מאפשר. זהו העלויות הנלוות לתחזוקה, שנועדו להבטיח שהזיהוי יהיה מקיף ועדכני.

עם זאת, במאגר של הנחיות הלקוח מסוג User-Agent מפורטים כמה תרחישים לדוגמה לאתרים.

מה קורה למחרוזת של סוכן המשתמש?

המטרה היא לצמצם את היכולת למעקב סמוי באינטרנט על ידי הפחתת כמות המידע המזהה שנחשף על ידי מחרוזת סוכן המשתמש הקיימת, בלי לגרום להפרעה מיותרת לאתרים קיימים. אנחנו משיקים את התכונה 'רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש' כדי לתת לכם הזדמנות להבין את היכולת החדשה ולנסות אותה, לפני שיבוצעו שינויים במחרוזות של סוכן המשתמש.

בסופו של דבר, המידע במחרוזת User-Agent יופחת כדי לשמור על הפורמט הקודם, תוך מתן אותם פרטים ברמה גבוהה על הדפדפן ועל הגרסה המשמעותית, בהתאם להנחיות ברירת המחדל. ב-Chromium, השינוי הזה נדחה לפחות עד שנת 2022 כדי לתת לסביבה העסקית זמן נוסף להעריך את היכולות החדשות של הלקוח של סוכן המשתמש.

אפשר לבדוק גרסה של התכונה הזו על ידי הפעלת הדגל about://flags/#reduce-user-agent ב-Chrome 93 (הערה: הדגל הזה נקרא about://flags/#freeze-user-agent בגרסאות Chrome 84 עד 92). הפונקציה הזו תחזיר מחרוזת עם הרשומות ההיסטוריות מסיבות תאימות, אבל עם פרטים ספציפיים שהושמטו. לדוגמה, משהו כזה:

Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36

תמונה ממוזערת של Sergey Zolkin ב-Unsplash