ไทยมีชุมชนนักพัฒนา Laravel/PHP ที่แข็งแกร่ง และเฟรมเวิร์กนี้มาพร้อมไฟล์ config/cors.php ตั้งแต่เวอร์ชัน 7 สถานการณ์ที่พบบ่อยคือตั้งค่า 'allowed_origins' => ['*'] ไว้ตอนพัฒนาเพื่อความสะดวก แล้วลืมจำกัดให้แคบลงก่อนขึ้น production มันยังทำงานได้ดีสำหรับคำขอ GET ธรรมดา จนกว่าทีมจะเปิด 'supports_credentials' => true เพื่อใช้ Sanctum ยืนยันตัวตนข้าม subdomain — ตอนนั้นเบราว์เซอร์จะเริ่มปฏิเสธการตอบกลับ เพราะ origin แบบ wildcard ใช้ร่วมกับ credentials ไม่ได้
นโยบาย Same-Origin
โดยค่าเริ่มต้น เบราว์เซอร์บังคับใช้นโยบาย Same-Origin: โค้ด JavaScript จากหน้าที่มาจากออริจินหนึ่ง (โดเมน + โปรโตคอล + พอร์ต) ไม่สามารถอ่านการตอบกลับของคำขอที่ส่งไปยังออริจินอื่นได้ นี่เป็นกลไกความปลอดภัยพื้นฐานที่ป้องกันไม่ให้โค้ดอันตรายในเว็บไซต์หนึ่งขโมยข้อมูลจากอีกเว็บไซต์ที่ผู้ใช้ล็อกอินอยู่
CORS ผ่อนปรนนโยบายนี้อย่างไร
CORS (Cross-Origin Resource Sharing) เป็นชุดของ HTTP headers ที่เซิร์ฟเวอร์อนุญาตอย่างชัดเจนให้ออริจินภายนอกที่ระบุ (หรือทั้งหมด) อ่านการตอบกลับของมันได้ เฮดเดอร์หลักคือ Access-Control-Allow-Origin ซึ่งระบุโดเมนที่ได้รับอนุญาต
กับดัก wildcard บวก credentials
เมื่อคำขอถูกส่งพร้อม credentials: 'include' — ซึ่งจำเป็นสำหรับส่งคุกกี้เซสชันไปยัง API บน subdomain อื่น — เบราว์เซอร์จะปฏิเสธ Access-Control-Allow-Origin: * ในการตอบกลับโดยสิ้นเชิง สเปกห้ามการรวม wildcard origin กับ credentials ไว้อย่างชัดเจน เซิร์ฟเวอร์ต้องส่ง origin ที่ตรงกับผู้ส่งคำขอกลับมาแทน
เหตุใดจึงจำเป็น
- วินิจฉัยข้อผิดพลาด CORS และหาว่าเฮดเดอร์ใดขาดหายไปบนเซิร์ฟเวอร์อย่างชัดเจน
- ตรวจจับการตั้งค่า
config/cors.phpของ Laravel ที่ยังหลวมเกินไปก่อนขึ้น production - เข้าใจความแตกต่างระหว่างคำขอ "แบบง่าย" กับคำขอ preflight (OPTIONS)
CORS ไม่ปกป้องเซิร์ฟเวอร์จากการโจมตี
ความเข้าใจผิดที่พบบ่อยคือคิดว่า CORS เป็นมาตรการความปลอดภัยฝั่งเซิร์ฟเวอร์ — แต่ในความเป็นจริงมันจำกัดแค่สิ่งที่ JavaScript ในเบราว์เซอร์สามารถอ่านได้เท่านั้น ผู้โจมตีที่ใช้ curl, Postman หรือสคริปต์แบ็กเอนด์โดยตรงจะข้าม CORS ไปได้ทั้งหมด เพราะเครื่องมือเหล่านี้ไม่บังคับใช้นโยบาย same-origin CORS ไม่ควรถูกมองว่าเป็นตัวแทนของการยืนยันตัวตนและการให้สิทธิ์ที่แท้จริงบนเซิร์ฟเวอร์