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