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

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

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

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

נעים להכיר: 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 מהאתר ושולח את ה-User-Agent הבסיסי שמוגדר כברירת מחדל.

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"

ממשק API של JavaScript

מלבד הכותרות, אפשר לגשת לסוכן המשתמש גם ב-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