กลไกการแชร์ทรัพยากรข้ามโดเมน (CORS)

แชร์ทรัพยากรแบบข้ามต้นทางอย่างปลอดภัย

Mariko Kosaka

นโยบายต้นทางเดียวกันของเบราว์เซอร์บล็อกการอ่านทรัพยากรจากต้นทางอื่น ซึ่งกลไกนี้ช่วยป้องกันไม่ให้เว็บไซต์ที่เป็นอันตรายอ่านข้อมูลของเว็บไซต์อื่นๆ แต่ก็ป้องกันการใช้งานที่ถูกกฎหมายด้วย

เว็บแอปสมัยใหม่มักต้องการทรัพยากรจากต้นทางอื่น เช่น ดึงข้อมูล JSON จากโดเมนอื่นหรือโหลดรูปภาพจากเว็บไซต์อื่นลงในองค์ประกอบ <canvas> ซึ่งอาจเป็นทรัพยากรสาธารณะที่ทุกคนควรอ่าน แต่นโยบายต้นทางเดียวกันจะบล็อกการใช้งานของผู้ใช้ ก่อนหน้านี้นักพัฒนาแอปได้ใช้วิธีแก้ปัญหาเบื้องต้น เช่น JSONP

กลไกการแชร์ทรัพยากรข้ามโดเมน (CORS) แก้ไขปัญหานี้ในวิธีที่เป็นมาตรฐาน การเปิดใช้ CORS จะทำให้เซิร์ฟเวอร์บอกเบราว์เซอร์ได้ว่าสามารถใช้ต้นทางเพิ่มเติมได้

คำขอทรัพยากรทำงานอย่างไรบนเว็บ

คำขอและคำตอบ
ภาพคำขอของไคลเอ็นต์และการตอบสนองของเซิร์ฟเวอร์

เบราว์เซอร์และเซิร์ฟเวอร์แลกเปลี่ยนข้อมูลผ่านเครือข่ายได้โดยใช้ Hypertext Transfer Protocol (HTTP) HTTP กำหนดกฎการสื่อสารระหว่างผู้ขอและผู้ตอบ รวมถึงข้อมูลที่จำเป็นต่อการรับทรัพยากร

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

ข้อมูลเกี่ยวกับข้อความ เช่น ประเภทข้อความหรือการเข้ารหัสของข้อความ ส่วนหัวอาจมีข้อมูลที่หลากหลายซึ่งแสดงเป็นคู่คีย์-ค่า ส่วนหัวของคำขอและส่วนหัวการตอบกลับมีข้อมูลที่แตกต่างกัน

ตัวอย่างส่วนหัวของคำขอ

Accept: text/html
Cookie: Version=1

ส่วนหัวนี้มีค่าเทียบเท่ากับการบอกว่า "ฉันต้องการรับ HTML ตอบกลับ นี่คือคุกกี้ที่ผมมี"

ตัวอย่างส่วนหัวการตอบกลับ

Content-Encoding: gzip
Cache-Control: no-store

ส่วนหัวนี้เทียบเท่ากับการบอกว่า "ข้อมูลในการตอบกลับนี้เข้ารหัสด้วย gzip อย่าสร้างแคชนี้"

เนื้อความ

ข้อความนั้นๆ ซึ่งอาจเป็นข้อความธรรมดา, ไบนารีของรูปภาพ, JSON, HTML หรือรูปแบบอื่นๆ

CORS ทำงานอย่างไร

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

ขั้นตอนที่ 1: คำขอของไคลเอ็นต์ (เบราว์เซอร์)

เมื่อเบราว์เซอร์ส่งคำขอข้ามต้นทาง เบราว์เซอร์จะเพิ่มส่วนหัว Origin ที่มีต้นทางปัจจุบัน (รูปแบบ โฮสต์ และพอร์ต)

ขั้นตอนที่ 2: การตอบกลับของเซิร์ฟเวอร์

เมื่อเซิร์ฟเวอร์เห็นส่วนหัวนี้และต้องการอนุญาตการเข้าถึง เซิร์ฟเวอร์จะเพิ่มส่วนหัว Access-Control-Allow-Origin ไปยังการตอบกลับที่ระบุต้นทางที่ส่งคำขอ (หรือ * เพื่ออนุญาตต้นทางใดก็ได้)

ขั้นตอนที่ 3: เบราว์เซอร์รับการตอบสนอง

เมื่อเบราว์เซอร์เห็นการตอบกลับนี้พร้อมกับส่วนหัว Access-Control-Allow-Origin ที่เหมาะสม เบราว์เซอร์จะแชร์ข้อมูลการตอบกลับกับเว็บไซต์ของไคลเอ็นต์

แชร์ข้อมูลเข้าสู่ระบบกับ CORS

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

ส่งคำขอ

เพิ่ม credentials: 'include' ลงในตัวเลือกการดึงข้อมูลตามตัวอย่างต่อไปนี้ ซึ่งรวมถึงคุกกี้ที่มีคำขอดังนี้:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

คำตอบ

ต้องตั้งค่า Access-Control-Allow-Origin เป็นต้นทางเฉพาะ (ไม่มีไวลด์การ์ดที่ใช้ *) และตั้งค่า Access-Control-Allow-Credentials เป็น true

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

คำขอการตรวจสอบล่วงหน้าสำหรับการเรียก HTTP ที่ซับซ้อน

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

ข้อกำหนด CORS กำหนดคำขอที่ซับซ้อนดังต่อไปนี้

  • คำขอที่ใช้เมธอดอื่นนอกเหนือจาก GET, POST หรือ HEAD
  • คำขอที่มีส่วนหัวที่ไม่ใช่ Accept, Accept-Language หรือ Content-Language
  • คำขอที่มีส่วนหัว Content-Type นอกเหนือจาก application/x-www-form-urlencoded, multipart/form-data หรือ text/plain

เบราว์เซอร์จะสร้างคำขอการตรวจสอบล่วงหน้าที่จำเป็นโดยอัตโนมัติ และส่งคำขอดังกล่าวก่อนข้อความคำขอจริง คำขอการตรวจสอบล่วงหน้าเป็นคำขอ OPTIONS ตามตัวอย่างต่อไปนี้

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

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

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

การตอบสนองของเซิร์ฟเวอร์ยังรวมส่วนหัว Access-Control-Max-Age เพื่อระบุระยะเวลาเป็นวินาทีเพื่อแคชผลลัพธ์การตรวจสอบล่วงหน้าได้ด้วย วิธีนี้ช่วยให้ไคลเอ็นต์ส่งคำขอที่ซับซ้อนหลายรายการได้โดยไม่ต้องทำตามคำขอการตรวจสอบล่วงหน้าซ้ำ