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

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

Mariko Kosaka

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

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

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

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

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

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

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

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

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

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

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

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

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