แชร์ทรัพยากรข้ามโดเมนอย่างปลอดภัย
นโยบายต้นทางเดียวกันของเบราว์เซอร์จะบล็อกการอ่านทรัพยากรจากต้นทางอื่น กลไกนี้จะป้องกันไม่ให้เว็บไซต์ที่เป็นอันตรายอ่านข้อมูลของเว็บไซต์อื่นๆ ได้ แต่ก็ป้องกันการใช้งานที่ถูกต้องด้วย
เว็บแอปสมัยใหม่มักต้องการทรัพยากรจากแหล่งที่มาอื่น เช่น การดึงข้อมูล 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
ฝั่งเซิร์ฟเวอร์ แอปที่ได้รับคําขอจะตอบกลับคําขอช่วงก่อนเข้าสู่ระยะการทำงานด้วยข้อมูลเกี่ยวกับวิธีการที่แอปพลิเคชันยอมรับจากต้นทางนี้
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS
การตอบกลับของเซิร์ฟเวอร์อาจมีส่วนหัว Access-Control-Max-Age
เพื่อระบุระยะเวลาเป็นวินาทีในการแคชผลการค้นหาก่อนแสดงผล ซึ่งช่วยให้ไคลเอ็นต์ส่งคำขอที่ซับซ้อนหลายรายการได้โดยไม่ต้องส่งคำขอช่วงก่อนเข้าสู่โหมดใช้งานซ้ำ