ไทย

ไขความลับของ CORS (Cross-Origin Resource Sharing) และเรียนรู้วิธีเปิดใช้งานการร้องขอข้ามโดเมนอย่างปลอดภัยในเว็บแอปพลิเคชันของคุณ คู่มือฉบับสมบูรณ์นี้ครอบคลุมทุกอย่างตั้งแต่พื้นฐานไปจนถึงการกำหนดค่าขั้นสูง เพื่อให้การสื่อสารระหว่าง Origin ที่แตกต่างกันเป็นไปอย่างราบรื่นและปลอดภัย

ไขข้อข้องใจเรื่อง CORS: คู่มือฉบับสมบูรณ์เกี่ยวกับ Cross-Origin Resource Sharing

ในโลกเว็บที่เชื่อมต่อถึงกันในปัจจุบัน แอปพลิเคชันต่างๆ มักจำเป็นต้องเข้าถึงทรัพยากรจาก Origin ที่แตกต่างกัน นี่คือจุดที่ Cross-Origin Resource Sharing (CORS) เข้ามามีบทบาท CORS เป็นกลไกความปลอดภัยที่สำคัญซึ่งควบคุมวิธีที่เว็บเบราว์เซอร์จัดการกับการร้องขอจาก Origin หนึ่ง (โดเมน โปรโตคอล และพอร์ต) ไปยัง Origin อื่น การทำความเข้าใจ CORS เป็นสิ่งจำเป็นสำหรับนักพัฒนาเว็บทุกคนเพื่อสร้างเว็บแอปพลิเคชันที่ปลอดภัยและทำงานได้อย่างสมบูรณ์

Same-Origin Policy คืออะไร?

ก่อนที่จะเจาะลึกเรื่อง CORS สิ่งสำคัญคือต้องทำความเข้าใจ Same-Origin Policy (SOP) ก่อน SOP เป็นกลไกความปลอดภัยพื้นฐานที่ใช้ในเว็บเบราว์เซอร์ มีวัตถุประสงค์เพื่อป้องกันไม่ให้สคริปต์ที่เป็นอันตรายบนเว็บไซต์หนึ่งเข้าถึงข้อมูลที่ละเอียดอ่อนบนเว็บไซต์อื่น Origin ถูกกำหนดโดยการรวมกันของโปรโตคอล (เช่น HTTP หรือ HTTPS) โดเมน (เช่น example.com) และหมายเลขพอร์ต (เช่น 80 หรือ 443) URL สองแห่งจะถือว่ามี Origin เดียวกันหากใช้โปรโตคอล โดเมน และพอร์ตเดียวกัน

ตัวอย่าง:

SOP จะจำกัดไม่ให้สคริปต์เข้าถึงทรัพยากรจาก Origin อื่น เว้นแต่จะมีมาตรการเฉพาะ เช่น CORS เพื่ออนุญาต

ทำไม CORS จึงจำเป็น?

แม้ว่า Same-Origin Policy จะมีความสำคัญอย่างยิ่งต่อความปลอดภัย แต่มันก็อาจมีข้อจำกัดเช่นกัน เว็บแอปพลิเคชันสมัยใหม่จำนวนมากต้องอาศัยการดึงข้อมูลจากเซิร์ฟเวอร์ต่างๆ เช่น API หรือเครือข่ายการจัดส่งเนื้อหา (CDN) CORS เป็นวิธีการที่ควบคุมได้ในการผ่อนคลายนโยบาย SOP และอนุญาตการร้องขอข้าม Origin ที่ถูกต้องตามกฎหมายในขณะที่ยังคงรักษาความปลอดภัยไว้

ลองพิจารณาสถานการณ์ที่เว็บแอปพลิเคชันที่โฮสต์บน http://example.com ต้องการดึงข้อมูลจากเซิร์ฟเวอร์ API ที่โฮสต์บน http://api.example.net หากไม่มี CORS เบราว์เซอร์จะบล็อกคำขอนี้เนื่องจาก SOP แต่ CORS จะช่วยให้เซิร์ฟเวอร์ API สามารถระบุได้อย่างชัดเจนว่า Origin ใดบ้างที่ได้รับอนุญาตให้เข้าถึงทรัพยากรของตน ทำให้เว็บแอปพลิเคชันสามารถทำงานได้อย่างถูกต้อง

CORS ทำงานอย่างไร: พื้นฐาน

CORS ทำงานผ่านชุดของ HTTP headers ที่แลกเปลี่ยนระหว่างไคลเอ็นต์ (เบราว์เซอร์) และเซิร์ฟเวอร์ เซิร์ฟเวอร์ใช้ headers เหล่านี้เพื่อแจ้งให้เบราว์เซอร์ทราบว่าได้รับอนุญาตให้เข้าถึงทรัพยากรที่ร้องขอหรือไม่ HTTP header ที่สำคัญที่เกี่ยวข้องคือ Access-Control-Allow-Origin

สถานการณ์ที่ 1: Simple Request (การร้องขอแบบง่าย)

"Simple request" คือคำขอ GET, HEAD หรือ POST ที่ตรงตามเกณฑ์เฉพาะ (เช่น header Content-Type เป็นหนึ่งใน application/x-www-form-urlencoded, multipart/form-data หรือ text/plain) ในกรณีนี้ เบราว์เซอร์จะส่งคำขอไปยังเซิร์ฟเวอร์โดยตรง และเซิร์ฟเวอร์จะตอบกลับด้วย header Access-Control-Allow-Origin

คำขอจากไคลเอ็นต์ (จาก http://example.com):

GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com

การตอบกลับจากเซิร์ฟเวอร์ (จาก http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "data": "Some data from the server"
}

ในตัวอย่างนี้ เซิร์ฟเวอร์ตอบกลับด้วย Access-Control-Allow-Origin: http://example.com ซึ่งบ่งชี้ว่าอนุญาตคำขอจาก http://example.com หาก Origin ในคำขอไม่ตรงกับค่าใน header Access-Control-Allow-Origin (หรือหากไม่มี header นี้) เบราว์เซอร์จะบล็อกการตอบกลับและป้องกันไม่ให้สคริปต์ฝั่งไคลเอ็นต์เข้าถึงข้อมูล

สถานการณ์ที่ 2: Preflight Request (สำหรับ Complex Requests)

สำหรับคำขอที่ซับซ้อนมากขึ้น เช่น คำขอที่ใช้เมธอด HTTP อย่าง PUT, DELETE หรือคำขอที่มี headers ที่กำหนดเอง เบราว์เซอร์จะทำการร้องขอ "preflight" โดยใช้เมธอด HTTP OPTIONS คำขอ preflight นี้จะถามเซิร์ฟเวอร์เพื่อขออนุญาตก่อนที่จะส่งคำขอจริง เซิร์ฟเวอร์จะตอบกลับด้วย headers ที่ระบุว่าอนุญาตเมธอด, headers และ Origin ใดบ้าง

คำขอ Preflight จากไคลเอ็นต์ (จาก http://example.com):

OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

การตอบกลับจากเซิร์ฟเวอร์ (จาก http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600

คำอธิบายเกี่ยวกับ Headers:

หากการตอบกลับ preflight ของเซิร์ฟเวอร์บ่งชี้ว่าคำขอได้รับอนุญาต เบราว์เซอร์จะดำเนินการส่งคำขอจริงต่อไป มิฉะนั้นเบราว์เซอร์จะบล็อกคำขอ

คำขอจริงจากไคลเอ็นต์ (จาก http://example.com):

PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json

{
  "data": "Some data to be updated"
}

การตอบกลับจากเซิร์ฟเวอร์ (จาก http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "status": "Data updated successfully"
}

CORS Headers ที่พบบ่อย

นี่คือรายละเอียดของ CORS headers ที่สำคัญที่คุณต้องทำความเข้าใจ:

CORS ในภาษาฝั่งเซิร์ฟเวอร์ต่างๆ

การนำ CORS ไปใช้งานโดยทั่วไปเกี่ยวข้องกับการกำหนดค่าแอปพลิเคชันฝั่งเซิร์ฟเวอร์ของคุณให้ส่ง CORS headers ที่เหมาะสม นี่คือตัวอย่างวิธีการทำในภาษาและเฟรมเวิร์กต่างๆ:

Node.js กับ Express

คุณสามารถใช้แพ็คเกจมิดเดิลแวร์ cors:

const express = require('express');
const cors = require('cors');

const app = express();

// เปิดใช้งาน CORS สำหรับทุก origin (โปรดใช้ด้วยความระมัดระวังในเวอร์ชัน Production)
app.use(cors());

// หรืออีกทางเลือกหนึ่ง กำหนดค่า CORS สำหรับ origin ที่ระบุ
// app.use(cors({
//   origin: 'http://example.com'
// }));

app.get('/data', (req, res) => {
  res.json({ message: 'This is CORS-enabled for all origins!' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Python กับ Flask

คุณสามารถใช้ส่วนขยาย Flask-CORS:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# หรืออีกทางเลือกหนึ่ง กำหนดค่า CORS สำหรับ origin ที่ระบุ
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})

@app.route("/data")
def hello():
    return {"message": "This is CORS-enabled for all origins!"}

if __name__ == '__main__':
    app.run(debug=True)

Java กับ Spring Boot

คุณสามารถกำหนดค่า CORS ในแอปพลิเคชัน Spring Boot ของคุณโดยใช้ annotations หรือ configuration classes:

การใช้ Annotations:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://example.com") // อนุญาตคำขอจาก http://example.com
public class DataController {

    @GetMapping("/data")
    public String getData() {
        return "This is CORS-enabled for http://example.com!";
    }
}

การใช้ Configuration:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/data")
                .allowedOrigins("http://example.com") // อนุญาตคำขอจาก http://example.com
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*");
    }
}

PHP

 "This is CORS-enabled for http://example.com!");
echo json_encode($data);
?>

CORS และข้อควรพิจารณาด้านความปลอดภัย

แม้ว่า CORS จะช่วยให้สามารถร้องขอข้าม Origin ได้ แต่สิ่งสำคัญคือต้องนำไปใช้อย่างปลอดภัย นี่คือข้อควรพิจารณาที่สำคัญบางประการ:

การแก้ไขปัญหา CORS

ปัญหา CORS อาจเป็นเรื่องน่าหงุดหงิดในการดีบัก นี่คือปัญหาที่พบบ่อยและวิธีแก้ไข:

เครื่องมือดีบัก:

สถานการณ์ CORS ขั้นสูง

แม้ว่าแนวคิดพื้นฐานของ CORS จะค่อนข้างตรงไปตรงมา แต่ก็มีสถานการณ์ขั้นสูงที่ต้องพิจารณา:

แนวทางปฏิบัติที่ดีที่สุดสำหรับ CORS

เพื่อให้แน่ใจว่าการนำ CORS ไปใช้งานนั้นปลอดภัยและมีประสิทธิภาพ ให้ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดเหล่านี้:

บทสรุป

CORS เป็นกลไกความปลอดภัยที่สำคัญซึ่งช่วยให้สามารถร้องขอข้าม Origin ที่มีการควบคุมในเว็บแอปพลิเคชันได้ การทำความเข้าใจว่า CORS ทำงานอย่างไรและวิธีกำหนดค่าอย่างถูกต้องเป็นสิ่งจำเป็นสำหรับนักพัฒนาเว็บทุกคน โดยการปฏิบัติตามแนวทางและแนวทางปฏิบัติที่ดีที่สุดที่ระบุไว้ในคู่มือฉบับสมบูรณ์นี้ คุณสามารถสร้างเว็บแอปพลิเคชันที่ปลอดภัยและทำงานได้อย่างสมบูรณ์ซึ่งโต้ตอบกับทรัพยากรจาก Origin ที่แตกต่างกันได้อย่างราบรื่น

อย่าลืมให้ความสำคัญกับความปลอดภัยเสมอและหลีกเลี่ยงการใช้การกำหนดค่า CORS ที่อนุญาตมากเกินไป ด้วยการพิจารณาถึงผลกระทบด้านความปลอดภัยของการตั้งค่า CORS ของคุณอย่างรอบคอบ คุณสามารถปกป้องแอปพลิเคชันและข้อมูลของคุณจากการเข้าถึงโดยไม่ได้รับอนุญาตได้

เราหวังว่าคู่มือนี้จะช่วยไขข้อข้องใจเรื่อง CORS ให้คุณได้ ขอให้สนุกกับการเขียนโค้ด!