ย้ายข้อมูลไปยังคำแนะนำของไคลเอ็นต์ User Agent

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

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

บทความนี้จะอธิบายเกี่ยวกับการตรวจสอบสิทธิ์ของคุณในการเข้าถึงข้อมูล User Agent และย้ายข้อมูลการใช้สตริง User Agent ไปยังคำแนะนำของไคลเอ็นต์ User Agent

การรวบรวมการตรวจสอบและการใช้ข้อมูล User Agent

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

หากไม่ทราบว่าระบบใช้ข้อมูล User-agent หรือไม่และที่ใด ให้ลองค้นหาโค้ดฝั่งหน้าเว็บเพื่อหาการใช้ navigator.userAgent และโค้ดฝั่งหลังเพื่อหาการใช้ส่วนหัว HTTP ของ User-Agent นอกจากนี้ คุณควรตรวจสอบโค้ดส่วนหน้าเพื่อใช้ฟีเจอร์ที่เลิกใช้งานแล้ว เช่น navigator.platform และ navigator.appVersion

จากมุมมองฟังก์ชัน ให้นึกถึงทุกจุดในโค้ดที่คุณบันทึกหรือประมวลผลข้อมูล

  • ชื่อหรือเวอร์ชันของเบราว์เซอร์
  • ชื่อหรือเวอร์ชันของระบบปฏิบัติการ
  • ยี่ห้อหรือรุ่นของอุปกรณ์
  • ประเภท CPU, สถาปัตยกรรม หรือบิตเนส (เช่น 64 บิต)

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

คุณใช้เฉพาะข้อมูล User Agent พื้นฐานใช่ไหม

ชุดคําแนะนําสําหรับไคลเอ็นต์ User Agent เริ่มต้นมีดังนี้

  • Sec-CH-UA: ชื่อเบราว์เซอร์และเวอร์ชันหลัก/สำคัญ
  • Sec-CH-UA-Mobile: ค่าบูลีนที่ระบุอุปกรณ์เคลื่อนที่
  • Sec-CH-UA-Platform: ชื่อระบบปฏิบัติการ
    • โปรดทราบว่าข้อมูลนี้ได้รับการอัปเดตในข้อกำหนดและจะแสดงใน Chrome และเบราว์เซอร์อื่นๆ ที่พัฒนาบน Chromium ในไม่ช้า

สตริง User Agent เวอร์ชันที่ลดลงซึ่งเราเสนอจะเก็บข้อมูลพื้นฐานนี้ไว้ด้วยในลักษณะที่เข้ากันได้แบบย้อนหลัง เช่น แทนที่จะเป็น Chrome/90.0.4430.85 สตริงจะมี Chrome/90.0.0.0

หากคุณตรวจสอบเฉพาะสตริง User-Agent สําหรับชื่อเบราว์เซอร์ เวอร์ชันหลัก หรือระบบปฏิบัติการ โค้ดจะยังคงทํางานต่อไปแม้ว่าคุณอาจเห็นคําเตือนการเลิกใช้งาน

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

กลยุทธ์: JavaScript API ฝั่งไคลเอ็นต์แบบออนดีมานด์

หากกำลังใช้ navigator.userAgent อยู่ คุณควรเปลี่ยนไปใช้ navigator.userAgentData ก่อนที่จะเปลี่ยนไปแยกวิเคราะห์สตริง User Agent

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
}

หากต้องการค่า User Agent ที่ละเอียดยิ่งขึ้นและมีข้อมูลเชิงตัวเลขสูง คุณจะต้องระบุค่าดังกล่าวและตรวจสอบผลลัพธ์ใน Promise ที่แสดงผล

navigator.userAgentData.getHighEntropyValues(['model'])
  .then(ua => {
    // requested hints available as attributes
    const model = ua.model
  });

นอกจากนี้ คุณอาจต้องใช้กลยุทธ์นี้หากต้องการเปลี่ยนจากการประมวลผลฝั่งเซิร์ฟเวอร์เป็นการประมวลผลฝั่งไคลเอ็นต์ JavaScript API ไม่จำเป็นต้องเข้าถึงส่วนหัวคำขอ HTTP คุณจึงขอค่า User Agent ได้ทุกเมื่อ

กลยุทธ์: ส่วนหัวฝั่งเซิร์ฟเวอร์แบบคงที่

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

ลองใช้กลยุทธ์นี้หากคุณกำลังเปลี่ยนรูปแบบหรือปรับแต่งคำตอบที่แสดงโดยอิงตามข้อมูล 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 หากไม่พร้อมใช้งาน

กลยุทธ์: การมอบหมายคำแนะนำให้กับคำขอข้ามต้นทาง

หากคุณขอทรัพยากรย่อยข้ามแหล่งที่มาหรือข้ามเว็บไซต์ที่กําหนดให้ต้องส่งคําแนะนําสําหรับไคลเอ็นต์ของ User Agent ในคําขอ คุณจะต้องระบุคําแนะนําที่ต้องการอย่างชัดเจนโดยใช้นโยบายสิทธิ์

ตัวอย่างเช่น สมมติว่า https://blog.site โฮสต์ทรัพยากรใน https://cdn.site ซึ่งสามารถแสดงผลทรัพยากรที่เพิ่มประสิทธิภาพสำหรับอุปกรณ์หนึ่งๆ ได้ https://blog.site สามารถขอคำแนะนำ Sec-CH-UA-Model ได้ แต่ต้องมอบสิทธิ์ให้กับ https://cdn.site อย่างชัดแจ้งโดยใช้ส่วนหัว Permissions-Policy รายการคำแนะนำที่ควบคุมโดยนโยบายมีอยู่ในโครงสร้างพื้นฐาน Client Hints

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

กลยุทธ์: การมอบหมายคำแนะนำไปยัง iframe

iframe ข้ามแหล่งที่มาทํางานคล้ายกับทรัพยากรข้ามแหล่งที่มา แต่คุณระบุคำแนะนำที่ต้องการมอบสิทธิ์ได้ในแอตทริบิวต์ allow

⬇️ คำตอบจาก blog.site

Accept-CH: Sec-CH-UA-Model

↪️ HTML สำหรับ blog.site

<iframe src="https://widget.site" allow="ch-ua-model"></iframe>

⬆️ ส่งคำขอไปยัง widget.site

Sec-CH-UA-Model: "Pixel 5"

แอตทริบิวต์ allow ใน iframe จะลบล้างส่วนหัว 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

กลยุทธ์: ต้องใช้คำแนะนำฝั่งเซิร์ฟเวอร์ในคำขอแรก

อาจมีกรณีที่คุณต้องระบุคำใบ้มากกว่าชุดค่าเริ่มต้นในคำขอแรก แต่กรณีนี้เกิดขึ้นไม่บ่อยนัก ดังนั้นโปรดตรวจสอบเหตุผล

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

คำแนะนำเพิ่มเติมสำหรับคำขอแรกมี 2 ตัวเลือก ก่อนอื่น คุณสามารถใช้ส่วนหัว 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

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

สำหรับกรณีที่คุณต้องการคำแนะนำเพิ่มเติมในการโหลดหน้าเว็บครั้งแรก ข้อเสนอความน่าเชื่อถือของคำแนะนำไคลเอ็นต์จะแสดงเส้นทางในการระบุคำแนะนำในการตั้งค่าระดับการเชื่อมต่อ ซึ่งจะใช้ประโยชน์จากส่วนขยาย Application-Layer Protocol Settings(ALPS) กับ TLS 1.3 เพื่อเปิดใช้การส่งคำแนะนำเกี่ยวกับการเชื่อมต่อ HTTP/2 และ HTTP/3 ในระยะแรก ขั้นตอนนี้ยังคงอยู่ในช่วงเริ่มต้น แต่หากคุณจัดการการตั้งค่า TLS และการเชื่อมต่อของตนเองอย่างสม่ำเสมอ นี่จึงเป็นโอกาสที่เหมาะสมในการมีส่วนร่วม

กลยุทธ์: การรองรับเวอร์ชันเก่า

คุณอาจมีโค้ดเดิมหรือโค้ดของบุคคลที่สามในเว็บไซต์ซึ่งใช้ navigator.userAgent รวมถึงสตริง User Agent บางส่วนที่จะลดลง คุณควรวางแผนที่จะเปลี่ยนไปใช้การโทร navigator.userAgentData ที่เทียบเท่ากันในระยะยาว แต่ก็ยังมีทางแก้ในระหว่างนี้

UA-CH retrofill เป็นไลบรารีขนาดเล็กที่ช่วยให้คุณเขียนทับ navigator.userAgent ด้วยสตริงใหม่ซึ่งสร้างขึ้นจากค่า navigator.userAgentData ที่ขอ

ตัวอย่างเช่น โค้ดนี้จะสร้างสตริง User Agent ที่มีคำแนะนำ "model" เพิ่มเข้ามา

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

การสนับสนุนเพิ่มเติม

หากกลยุทธ์เหล่านี้ไม่ครอบคลุม Use Case ของคุณ โปรดเริ่มการสนทนาใน repo ของ privacy-sandbox-dev-support แล้วเราจะได้หาทางแก้ปัญหาไปด้วยกัน

รูปภาพโดย Ricardo Rocha ใน Unsplash