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

User-Agent Client Hints הם הרחבה חדשה של Client Hints API שמאפשרת למפתחים לגשת למידע על הדפדפן של המשתמש בצורה ארגונומית ושמירה על הפרטיות.

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

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

רקע

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

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

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

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

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

Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4076.0 Mobile Safari/537.36

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

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

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

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

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

טיפים ללקוחות של סוכן משתמש מ-Chromium 89

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

היקף רמזים ובקשות ממקורות שונים

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

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

איפה משתמשים ברמזים של סוכן משתמש ללקוח?

התשובה המהירה היא שצריך לארגן מחדש את כל המופעים שבהם מנתחים את הכותרת של סוכן המשתמש או משתמשים בקריאות JavaScript שניגשות לאותו מידע (למשל navigator.userAgent, navigator.appVersion או navigator.platform) כדי להשתמש בטיפים ללקוח של סוכן משתמש.

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

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

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

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

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

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

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

תמונה ממוזערת של סרגיי זולקין ב-Unbounce