สูตรคุกกี้ SameSite

Chrome, Firefox, Edge และอีกมากมายกำลังเปลี่ยนลักษณะการทำงานเริ่มต้นให้สอดคล้องกับข้อเสนอของ IETF คุกกี้ที่ดีขึ้นเรื่อยๆ เพื่อให้

  • คุกกี้ที่ไม่มีแอตทริบิวต์ SameSite จะถือว่าเป็น SameSite=Lax ซึ่งหมายความว่าลักษณะการทำงานเริ่มต้นคือจำกัดคุกกี้ให้อยู่ในบริบทของบุคคลที่หนึ่งเท่านั้น
  • คุกกี้สำหรับการใช้งานข้ามเว็บไซต์ต้องระบุ SameSite=None; Secure เพื่อเปิดใช้การรวมในบริบทของบุคคลที่สาม

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

การสนับสนุนเบราว์เซอร์

  • 51
  • 16
  • 60
  • 13

แหล่งที่มา

กรณีการใช้งานสำหรับคุกกี้ข้ามเว็บไซต์หรือคุกกี้ของบุคคลที่สาม

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

เนื้อหาภายใน <iframe>

เนื้อหาจากเว็บไซต์อื่นที่แสดงใน <iframe> อยู่ในบริบทของบุคคลที่สาม กรณีการใช้งานมาตรฐานมีดังนี้

  • เนื้อหาที่ฝังซึ่งแชร์จากเว็บไซต์อื่นๆ เช่น วิดีโอ แผนที่ ตัวอย่างโค้ด และโพสต์บนโซเชียลเน็ตเวิร์ก
  • วิดเจ็ตจากบริการภายนอก เช่น ฟีเจอร์การชำระเงิน ปฏิทิน การจอง และการจอง
  • วิดเจ็ต เช่น ปุ่มโซเชียลหรือบริการป้องกันการประพฤติมิชอบที่ไม่ชัดเจนนัก <iframes>

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

แผนภาพหน้าต่างเบราว์เซอร์ซึ่ง URL ของเนื้อหาที่ฝังไม่ตรงกับ URL ของหน้าเว็บ
หากเนื้อหาที่ฝังไม่ได้มาจากเว็บไซต์เดียวกับบริบทการท่องเว็บระดับบนสุด แสดงว่าเป็นเนื้อหาของบุคคลที่สาม

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

คำขอ "ไม่ปลอดภัย" ในเว็บไซต์ต่างๆ

คำว่า "ไม่ปลอดภัย" อาจฟังดูน่ากังวล แต่หมายถึงคำขอใดๆ ที่มีเจตนาให้เปลี่ยนสถานะ สำหรับบนเว็บ นั่นเป็นคำขอ POST เป็นหลัก ระบบจะส่งคุกกี้ที่มีเครื่องหมาย SameSite=Lax ในการนำทางระดับบนสุดที่ปลอดภัย เช่น การคลิกลิงก์เพื่อไปยังเว็บไซต์อื่น อย่างไรก็ตาม ตัวอย่างเช่น การส่ง <form> ไปยังเว็บไซต์อื่นโดยใช้ POST จะไม่รวมถึงคุกกี้

แผนภาพแสดงคำขอที่ย้ายจากหน้าหนึ่งไปอีกหน้าหนึ่ง
หากคำขอขาเข้าใช้วิธีการ "ปลอดภัย" หน้านั้นจะส่งคุกกี้

รูปแบบนี้ใช้สำหรับเว็บไซต์ที่สามารถเปลี่ยนเส้นทางผู้ใช้ออกไปยังบริการระยะไกลเพื่อดำเนินการบางอย่างก่อนส่งคืน เช่น การเปลี่ยนเส้นทางไปยังผู้ให้บริการข้อมูลประจำตัวบุคคลที่สาม ก่อนที่ผู้ใช้จะออกจากเว็บไซต์ ระบบจะตั้งค่าคุกกี้ที่มีโทเค็นแบบใช้ครั้งเดียวโดยคาดหวังว่าสามารถตรวจสอบโทเค็นนี้ได้ในคำขอที่ส่งคืนเพื่อลดการโจมตีด้วยการปลอมแปลงคำขอข้ามเว็บไซต์ (CSRF) หากคำขอส่งคืนดังกล่าวมาจาก POST คุณจะต้องทำเครื่องหมายคุกกี้เป็น SameSite=None; Secure

ทรัพยากรระยะไกล

ทรัพยากรระยะไกลในหน้าเว็บ เช่น จากแท็ก <img> หรือแท็ก <script> อาจต้องใช้คุกกี้ที่ส่งไปพร้อมกับคำขอ กรณีการใช้งานทั่วไป ได้แก่ การติดตามพิกเซลและการปรับเปลี่ยนเนื้อหาในแบบของคุณ

ซึ่งรวมถึงคำขอที่ส่งจาก JavaScript ที่ใช้ fetch หรือ XMLHttpRequest ด้วย หากเรียกใช้ fetch() ด้วยตัวเลือก credentials: 'include' คําขอเหล่านั้นมีแนวโน้มที่จะรวมคุกกี้ สําหรับ XMLHttpRequest คุกกี้ที่คาดไว้มักจะระบุด้วยค่า withCredentials สําหรับ true และต้องทำเครื่องหมายคุกกี้เหล่านั้นอย่างเหมาะสมเพื่อให้รวมอยู่ในคำขอแบบข้ามเว็บไซต์

เนื้อหาภายใน WebView

WebView ในแอปเฉพาะแพลตฟอร์มขับเคลื่อนโดยเบราว์เซอร์ นักพัฒนาแอปต้องทดสอบว่าข้อจำกัดหรือปัญหาที่ส่งผลต่อแอปมีผลกับ WebView ของแอปด้วยหรือไม่

นอกจากนี้ Android ยังอนุญาตให้แอปเฉพาะแพลตฟอร์มตั้งค่าคุกกี้ได้โดยตรงโดยใช้ CookieManager API เช่นเดียวกับคุกกี้ที่ตั้งค่าโดยใช้ส่วนหัวหรือ JavaScript ให้พิจารณาใส่ SameSite=None; Secure หากมีไว้เพื่อการใช้งานแบบข้ามเว็บไซต์

วิธีติดตั้งใช้งาน SameSite วันนี้เลย

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

Set-Cookie: first_party_var=value; SameSite=Lax

อย่าลืมทำเครื่องหมายคุกกี้ที่จำเป็นในบริบทของบุคคลที่สามเป็น SameSite=None; Secure โดยต้องระบุทั้ง 2 แอตทริบิวต์ หากคุณเพียงระบุ None โดยไม่มี Secure คุกกี้จะถูกปฏิเสธ หากต้องการอธิบายความแตกต่างในการใช้งานเบราว์เซอร์ คุณอาจต้องใช้กลยุทธ์ในการลดความเสี่ยงบางอย่างที่อธิบายไว้ในหัวข้อจัดการไคลเอ็นต์ที่เข้ากันไม่ได้

Set-Cookie: third_party_var=value; SameSite=None; Secure

จัดการไคลเอ็นต์ที่ทำงานร่วมกันไม่ได้

เนื่องจากการเปลี่ยนแปลงที่รวม None และลักษณะการทํางานเริ่มต้นในการอัปเดตยังค่อนข้างใหม่ เบราว์เซอร์ที่แตกต่างกันจะจัดการกับการเปลี่ยนแปลงด้วยวิธีที่ต่างกัน ดูรายการปัญหาที่ทราบได้ที่หน้าอัปเดตใน chromium.org แต่รายการนี้อาจไม่ครอบคลุมทั้งหมด

วิธีแก้ไขปัญหาเฉพาะหน้าหนึ่งที่สามารถทำได้คือการตั้งค่าคุกกี้แต่ละรายการทั้งในสไตล์ใหม่และเก่า

Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure

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

ตัวอย่างต่อไปนี้แสดงวิธีดำเนินการใน Node.js โดยใช้เฟรมเวิร์กของ Express และมิดเดิลแวร์cookie-parser

const express = require('express');
const cp = require('cookie-parser');
const app = express();
app.use(cp());

app.get('/set', (req, res) => {
  // Set the new style cookie
  res.cookie('3pcookie', 'value', { sameSite: 'none', secure: true });
  // And set the same value in the legacy cookie
  res.cookie('3pcookie-legacy', 'value', { secure: true });
  res.end();
});

app.get('/', (req, res) => {
  let cookieVal = null;

  if (req.cookies['3pcookie']) {
    // check the new style cookie first
    cookieVal = req.cookies['3pcookie'];
  } else if (req.cookies['3pcookie-legacy']) {
    // otherwise fall back to the legacy cookie
    cookieVal = req.cookies['3pcookie-legacy'];
  }

  res.end();
});

app.listen(process.env.PORT);

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

หรือคุณจะตรวจหาไคลเอ็นต์โดยใช้สตริง User Agent เมื่อมีการส่งส่วนหัว Set-Cookie ก็ได้ โปรดดูรายการไคลเอ็นต์ที่เข้ากันไม่ได้และใช้ไลบรารีการตรวจจับ User Agent ที่เหมาะสมสำหรับแพลตฟอร์มของคุณ เช่น ไลบรารี ua-parser-js ใน Node.js วิธีนี้เพียงต้องการให้คุณทำการเปลี่ยนแปลง 1 ครั้ง แต่การดักจับ User Agent อาจไม่ตรวจจับผู้ใช้ที่ได้รับผลกระทบครบทุกคน

การรองรับ SameSite=None ในภาษา ไลบรารี และเฟรมเวิร์ก

ภาษาและไลบรารีส่วนใหญ่รองรับแอตทริบิวต์ SameSite สำหรับคุกกี้ อย่างไรก็ตาม เนื่องจากการเพิ่ม SameSite=None ยังค่อนข้างเกิดขึ้นเมื่อเร็วๆ นี้ คุณจึงอาจต้องหลีกเลี่ยงการทำงานที่เป็นมาตรฐานบางอย่างไปก่อนในขณะนี้ ลักษณะการทํางานเหล่านี้บันทึกไว้ในที่เก็บตัวอย่าง SameSite รายการใน GitHub

การขอความช่วยเหลือ

มีการใช้คุกกี้ทุกที่บนเว็บ และทีมพัฒนาจะทราบได้ยากว่าเว็บไซต์ของตนตั้งค่าและใช้งานคุกกี้ที่ไหน โดยเฉพาะอย่างยิ่งใน Use Case แบบข้ามเว็บไซต์ เมื่อคุณพบปัญหา อาจเป็นครั้งแรกที่ มีใครประสบกับปัญหานี้ ดังนั้นโปรดติดต่อเรา