Skip to content

CORS ​

CORS (Cross-Origin Resource Sharing) là lỗi/khái niệm gần như mọi người mới đều gặp đầu tiên khi bắt đầu gọi API từ frontend: browser chặn request, console báo blocked by CORS policy, dù gọi thẳng bằng Postman/curl thì lại chạy bình thường. Hiểu đúng CORS giúp không hoảng khi gặp lỗi này, và không "tắt bừa" theo cách làm lộ lỗ hổng bảo mật.

Same-origin policy — vì sao CORS tồn tại ​

Trình duyệt mặc định áp dụng same-origin policy: 1 trang web ở origin A (ví dụ https://app.example.com) không được phép đọc response từ 1 origin B khác (ví dụ https://api.example.com) trừ khi origin B cho phép rõ ràng. "Origin" được tính bằng 3 yếu tố: protocol + domain + port — chỉ cần khác 1 trong 3 là khác origin (kể cả http:// vs https:// cùng domain, hay :3000 vs :8080).

Đây là cơ chế bảo vệ người dùng: nếu không có same-origin policy, 1 trang web độc hại bất kỳ có thể âm thầm gọi API ngân hàng bạn đang đăng nhập và đọc được dữ liệu trả về. CORS là cơ chế để server chủ động nới lỏng giới hạn này cho những origin nó tin tưởng.

Cách hoạt động ​

Server trả về các header cho biết origin nào được phép gọi:

HeaderÝ nghĩa
Access-Control-Allow-OriginOrigin nào được phép đọc response (* = cho phép tất cả, hoặc 1 domain cụ thể)
Access-Control-Allow-MethodsHTTP method nào được phép (GET, POST, PUT...)
Access-Control-Allow-HeadersHeader nào client được phép gửi kèm
Access-Control-Allow-CredentialsCó cho phép gửi kèm cookie/credential cross-origin không

Preflight request — request "dò đường" trước ​

Với các request "không đơn giản" (ví dụ dùng method PUT/DELETE, hoặc có header tuỳ chỉnh như Authorization), trình duyệt tự động gửi trước 1 request OPTIONS (gọi là preflight) để hỏi server "tôi được phép gửi request thật không". Chỉ khi server trả lời đồng ý (đúng header CORS), trình duyệt mới gửi tiếp request thật. Đây là lý do đôi khi thấy 2 request cho 1 lần gọi API trong tab Network của DevTools.

Sai lầm thường gặp ​

  • Dùng Access-Control-Allow-Origin: * cho API có xác thực (cookie/session) — * không được phép dùng chung với Access-Control-Allow-Credentials: true (browser sẽ tự chặn), và kể cả khi kỹ thuật cho phép được thì đây vẫn là cấu hình quá lỏng lẻo, mở API cho mọi origin trên internet gọi được.
  • Nhầm CORS là cơ chế bảo mật API — CORS chỉ bảo vệ trình duyệt của người dùng, không bảo vệ được server. Ai đó gọi thẳng API qua curl/Postman/backend khác thì CORS không chặn được gì cả (không có "trình duyệt" nào để áp policy). Muốn bảo vệ API thực sự vẫn phải dựa vào authentication/authorization.
  • "Tắt CORS" ở phía client để hết lỗi — lỗi CORS chỉ sửa được ở phía server (server phải trả đúng header cho phép), sửa ở phía client (tắt security của trình duyệt, dùng proxy che mắt lúc dev) chỉ là né tạm trong lúc phát triển, không phải giải pháp cho production.