การปรับปรุงความเป็นส่วนตัวของผู้ใช้และประสบการณ์ของนักพัฒนาซอฟต์แวร์ด้วยคำแนะนำสำหรับไคลเอ็นต์ User Agent

User-Agent Client Hints คือการขยายตัวใหม่ของ Client Hints API ซึ่งช่วยให้นักพัฒนาซอฟต์แวร์เข้าถึงข้อมูลเกี่ยวกับเบราว์เซอร์ของผู้ใช้ได้ด้วยวิธีการรักษาความเป็นส่วนตัวและหลักสรีรศาสตร์

คำแนะนำไคลเอ็นต์ช่วยให้นักพัฒนาซอฟต์แวร์ขอข้อมูลเกี่ยวกับอุปกรณ์หรือเงื่อนไขของผู้ใช้ได้อย่างสม่ำเสมอ แทนที่จะต้องแยกวิเคราะห์ออกจากสตริง User-Agent (UA) การระบุเส้นทางทางเลือกนี้เป็นขั้นตอนแรกในการลดความละเอียดของสตริง User-Agent ในที่สุด

ดูวิธีอัปเดตฟังก์ชันที่มีอยู่ซึ่งอาศัยการแยกวิเคราะห์สตริง User-Agent เพื่อใช้ประโยชน์จากคำแนะนำของไคลเอ็นต์ User Agent แทน

ที่มา

เมื่อเว็บเบราว์เซอร์ส่งคำขอ จะมีข้อมูลเกี่ยวกับเบราว์เซอร์และสภาพแวดล้อมของเว็บเบราว์เซอร์เพื่อให้เซิร์ฟเวอร์เปิดใช้ข้อมูลวิเคราะห์และปรับแต่งการตอบสนองได้ ซึ่งกำหนดไว้ในปี 1996 (RFC 1945 สำหรับ HTTP/1.0) ซึ่งคุณจะดูคำจำกัดความเดิมของสตริง User-Agent ได้ ซึ่งมีตัวอย่างดังนี้

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

ส่วนหัวนี้มีจุดประสงค์เพื่อระบุผลิตภัณฑ์ (เช่น เบราว์เซอร์หรือคลัง) และความคิดเห็น (เช่น เวอร์ชัน) ตามลำดับความสำคัญ

สถานะของสตริง User Agent

ในช่วงทศวรรษที่ผ่านไป สตริงนี้มีรายละเอียดเพิ่มเติมมากมายเกี่ยวกับไคลเอ็นต์ที่ส่งคำขอ (รวมถึงสิ่งที่เกินความจำเป็นเนื่องจากความเข้ากันได้แบบย้อนหลัง) เมื่อดูสตริง 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

สตริงข้างต้นมีข้อมูลเกี่ยวกับระบบปฏิบัติการและเวอร์ชันของผู้ใช้ รุ่นอุปกรณ์ แบรนด์ของเบราว์เซอร์ และเวอร์ชันเต็ม ซึ่งข้อมูลเพียงพอที่จะสรุปว่าเป็นเบราว์เซอร์ในอุปกรณ์เคลื่อนที่ และไม่ต้องมีการอ้างอิงถึงเบราว์เซอร์อื่นๆ จำนวนมากด้วยเหตุผลด้านประวัติ

การใช้พารามิเตอร์เหล่านี้ร่วมกับค่าที่เป็นไปได้หลากหลายมากหมายความว่าสตริง User-Agent อาจมีข้อมูลเพียงพอที่จะระบุผู้ใช้แต่ละรายได้อย่างไม่ซ้ำกัน

สตริง User Agent เปิดใช้ Use Case ที่ถูกต้องมากมายและมีจุดประสงค์ที่สำคัญสำหรับนักพัฒนาซอฟต์แวร์และเจ้าของเว็บไซต์ อย่างไรก็ตาม การปกป้องความเป็นส่วนตัวของผู้ใช้จากวิธีการติดตามที่แอบแฝงเป็นสิ่งสำคัญเช่นกัน และการส่งข้อมูล UA โดยค่าเริ่มต้นจะไม่เป็นไปตามเป้าหมายนั้น

ทั้งยังต้องปรับปรุงความเข้ากันได้กับเว็บในเรื่องของสตริง User-Agent เนื่องจากไม่มีโครงสร้าง การแยกวิเคราะห์จึงทำให้มีความซับซ้อนโดยไม่จำเป็น ซึ่งมักเป็นสาเหตุของข้อบกพร่องและปัญหาความเข้ากันได้ของเว็บไซต์ที่ทำร้ายผู้ใช้ ปัญหาเหล่านี้ยังส่งผลเสียต่อผู้ใช้เบราว์เซอร์ที่ไม่ค่อยพบบ่อยอย่างไม่ได้สัดส่วน เนื่องจากเว็บไซต์อาจทดสอบการกำหนดค่าไม่สำเร็จ

ขอแนะนำคำแนะนำไคลเอ็นต์ User Agent ใหม่

คำแนะนำสำหรับไคลเอ็นต์ User Agent ช่วยให้เข้าถึงข้อมูลเดียวกันแต่เป็นการรักษาความเป็นส่วนตัวได้มากขึ้น โดยจะเปิดใช้เบราว์เซอร์เพื่อลดค่าเริ่มต้นของสตริง User Agent ในการส่งข้อมูลทุกอย่าง คำแนะนำไคลเอ็นต์ จะบังคับใช้รูปแบบที่เซิร์ฟเวอร์ต้องขอชุดข้อมูลเกี่ยวกับไคลเอ็นต์จากเบราว์เซอร์ (คำแนะนำ) และเบราว์เซอร์จะใช้นโยบายหรือการกำหนดค่าผู้ใช้ของตนเองเพื่อกำหนดข้อมูลที่จะส่งคืน ซึ่งหมายความว่าแทนที่จะเปิดเผยข้อมูล User-Agent ทั้งหมดโดยค่าเริ่มต้น ตอนนี้การเข้าถึงจะได้รับการจัดการด้วยรูปแบบที่ชัดเจนและตรวจสอบได้ นักพัฒนาซอฟต์แวร์ยังได้รับประโยชน์จาก API ที่ง่ายขึ้นด้วย ซึ่งไม่มีนิพจน์ปกติอีกต่อไป

ชุดคำแนะนำของไคลเอ็นต์ในปัจจุบันจะอธิบายความสามารถในการแสดงผลและการเชื่อมต่อของเบราว์เซอร์เป็นหลัก ดูรายละเอียดได้ใน Automating Resource Selection with Client Hints แต่นี่เป็นการทบทวนกระบวนการนี้แบบคร่าวๆ

เซิร์ฟเวอร์จะขอคำแนะนำของไคลเอ็นต์ที่เจาะจงผ่านส่วนหัว ดังนี้

⬇️ การตอบกลับจากเซิร์ฟเวอร์

Accept-CH: Viewport-Width, Width

หรือเมตาแท็ก

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

จากนั้นเบราว์เซอร์จะเลือกส่งส่วนหัวต่อไปนี้กลับมาในคำขอที่ตามมาได้

⬆️ คำขอลำดับต่อมา

Viewport-Width: 460
Width: 230

เซิร์ฟเวอร์จะเลือกให้การตอบสนองต่างกันได้ เช่น แสดงรูปภาพในความละเอียดที่เหมาะสม

คำแนะนำของไคลเอ็นต์ User Agent จะขยายช่วงของพร็อพเพอร์ตี้ด้วยคำนำหน้า Sec-CH-UA ที่ระบุผ่านส่วนหัวการตอบกลับของเซิร์ฟเวอร์ Accept-CH ได้ สำหรับรายละเอียดทั้งหมด ให้เริ่มต้นด้วยคำอธิบาย แล้วเจาะลึกข้อเสนอฉบับเต็ม

คำแนะนำไคลเอ็นต์ User Agent จาก Chromium 89

เปิดใช้งานคำแนะนำไคลเอ็นต์ของ User Agent เป็นค่าเริ่มต้นใน 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"

ส่วนหัวการตอบกลับและคําขอของ User Agent

⬇️ การตอบกลับ 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"

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" …> ด้วย คำแนะนำที่ขอไปจะส่งตามคำขอที่เริ่มโดยหน้าดังกล่าวเท่านั้น และจะไม่ส่งในการนำทางที่ตามมา

ขอบเขตคำแนะนำและคำขอข้ามต้นทาง

โดยค่าเริ่มต้น ระบบจะส่งคำแนะนำเกี่ยวกับไคลเอ็นต์ในคำขอต้นทางเดียวกันเท่านั้น นั่นหมายความว่าหากคุณขอคำแนะนำที่เจาะจงเกี่ยวกับ https://example.com แต่ทรัพยากรที่ต้องการเพิ่มประสิทธิภาพนั้นอยู่ใน https://downloads.example.com ทรัพยากรดังกล่าวจะไม่ได้รับคำแนะนำใดๆ เลย

หากต้องการอนุญาตคำแนะนำเกี่ยวกับคำขอข้ามต้นทาง คุณต้องระบุคำแนะนำและต้นทางแต่ละรายการด้วยส่วนหัว Permissions-Policy หากต้องการใช้กับคำแนะนำของไคลเอ็นต์ User Agent คุณจะต้องพิมพ์คำแนะนำเป็นตัวพิมพ์เล็กและนำคำนำหน้า 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

วิธีใช้คำแนะนำไคลเอ็นต์ User Agent

คำตอบด่วนคือคุณควรเปลี่ยนโครงสร้างภายในโค้ดในกรณีที่แยกวิเคราะห์ส่วนหัว User-Agent หรือใช้การเรียก JavaScript ที่เข้าถึงข้อมูลเดียวกัน (เช่น navigator.userAgent, navigator.appVersion หรือ navigator.platform) เพื่อใช้ประโยชน์จากคำแนะนำของไคลเอ็นต์ User-Agent แทน

ในการดำเนินการเพิ่มเติม คุณควรตรวจสอบการใช้ข้อมูล User-Agent อีกครั้งและแทนที่ด้วยวิธีการอื่นหากเป็นไปได้ บ่อยครั้ง คุณสามารถบรรลุเป้าหมายเดียวกันได้โดยใช้การเพิ่มประสิทธิภาพแบบต่อเนื่อง การตรวจหาฟีเจอร์ หรือการออกแบบที่ปรับเปลี่ยนตามอุปกรณ์ ปัญหาพื้นฐานที่เกี่ยวข้องกับการอาศัยข้อมูล User-Agent คือคุณมักจัดการแมประหว่างพร็อพเพอร์ตี้ที่กําลังตรวจสอบกับลักษณะการทํางานที่พร็อพเพอร์ตี้เปิดใช้ มีค่าใช้จ่ายในการบำรุงรักษาเพื่อให้การตรวจหามีความครอบคลุมและเป็นปัจจุบันอยู่เสมอ

ดังนั้นที่เก็บคำแนะนำของไคลเอ็นต์สำหรับ User Agent จะแสดงกรณีการใช้งานที่ถูกต้องสำหรับเว็บไซต์ข้อควรระวังเหล่านี้

จะเกิดอะไรขึ้นกับสตริง User Agent

แผนการคือจะลดความสามารถในการติดตามโดยไม่เปิดเผยบนเว็บโดยลดจำนวนข้อมูลระบุที่เปิดเผยโดยสตริง User-Agent ที่มีอยู่ ขณะเดียวกันก็ไม่ทำให้เว็บไซต์ที่มีอยู่หยุดชะงัก ขอแนะนำ User-Agent Client Hints ตอนนี้จะเปิดโอกาสให้คุณได้ทำความเข้าใจและทดสอบความสามารถใหม่ก่อนที่จะทำการเปลี่ยนแปลงใดๆ กับสตริง User Agent

ท้ายที่สุด ข้อมูลในสตริง User-Agent จะลดลงเพื่อให้ยังคงรักษารูปแบบเดิมไว้ไปพร้อมกับระบุเบราว์เซอร์ระดับสูงและข้อมูลเวอร์ชันที่สำคัญตามคำแนะนำเริ่มต้นเท่านั้น การเปลี่ยนแปลงนี้ใน Chromium ได้รับการเลื่อนเวลาไปจนถึงปี 2022 เป็นอย่างน้อย เพื่อให้ระบบนิเวศประเมินความสามารถของ User Agent แบบใหม่ของไคลเอ็นต์ User Agent

คุณทดสอบเวอร์ชันของเวอร์ชันนี้ได้โดยเปิดใช้ Flag about://flags/#reduce-user-agent จาก Chrome 93 (หมายเหตุ: Flag นี้มีชื่อว่า 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