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