CORS (Cross-Origin Resource Sharing) Là Gì? Giải Thích Dễ Hiểu Cho Người Mới

Câu trả lời nhanh
CORS (Cross-Origin Resource Sharing) là cơ chế bảo mật của trình duyệt, cho phép trang web truy cập tài nguyên từ domain khác. Khi frontend gọi API ở domain khác, server cần trả về header Access-Control-Allow-Origin để trình duyệt cho phép request. Không có CORS, request bị chặn.

CORS Là Gì?

CORS là gì - chia sẻ tài nguyên khác nguồn

CORS (Cross-Origin Resource Sharing) là cơ chế bảo mật của trình duyệt, cho phép một trang web truy cập tài nguyên từ domain khác với domain hiện tại. Khi trình duyệt chặn request cross-origin, CORS chính là cầu nối giúp các resource được chia sẻ an toàn.

Nói đơn giản hơn: bạn có trang web tại example.com, muốn gọi API ở api.example.com hoặc another-domain.com. Trình duyệt mặc định sẽ chặn request này vì lý do bảo mật. CORS cung cấp cách để server nói với trình duyệt: “OK, cho domain này truy cập nhé.”

Tại Sao CORS Ra Đời?

Trước CORS, trình duyệt áp dụng Same-Origin Policy (SOP) — quy tắc nghiêm ngặt rằng JavaScript chỉ được gọi resource trong cùng domain. Quy tắc này ngăn chặn các cuộc tấn công đọc dữ liệu chéo trang, nhưng đồng thời cũng chặn luôn những trường hợp hợp lệ.

Mình tưởng tượng bạn xây dựng một SPA (Single Page Application) ở frontend myapp.com, còn backend API nằm ở api.myapp.com. Theo SOP, trình duyệt coi hai domain này là khác origin (vì hostname khác nhau) và chặn request. Bạn không gọi được API của chính mình. CORS sinh ra để giải quyết vấn đề này một cách có kiểm soát.

CORS Hoạt Động Như Thế Nào?

CORS hoạt động dựa trên các HTTP header mà server gửi về. Có hai loại request cần hiểu rõ:

1. Simple Request (Request Đơn Giản)

Khi request thỏa mãn điều kiện (dùng GET/POST/HEAD, chỉ dùng header cơ bản, Content-Type đơn giản), trình duyệt gửi thẳng đến server. Server phản hồi với header Access-Control-Allow-Origin:

Access-Control-Allow-Origin: https://myapp.com

Nếu origin của trang web khớp với giá trị này, trình duyệt cho phép đọc response. Nếu không, response bị chặn.

2. Preflight Request (Request Kiểm Tra Trước)

Khi request phức tạp hơn (dùng PUT/DELETE, header tùy chỉnh, Content-Type đặc biệt), trình duyệt gửi trước một request OPTIONS để hỏi server: “Tôi được phép gửi request này không?” Đây gọi là preflight request.

Server phản hồi bằng các header CORS tương ứng:

Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600

Nếu preflight thành công, trình duyệt mới gửi request thật. Nếu thất bại, trình duyệt chặn và bạn thấy lỗi quen thuộc trong console.

Các CORS Header Quan Trọng

Dưới đây là những header quyết định việc chia sẻ resource có được phép hay không:

Access-Control-Allow-Origin — Chỉ định origin nào được phép truy cập. Dùng * cho tất cả, nhưng cần cẩn thận vì không an toàn cho mọi trường hợp.

Access-Control-Allow-Methods — Liệt kê các HTTP method được cho phép (GET, POST, PUT, DELETE…).

Access-Control-Allow-Headers — Cho biết header nào client được gửi kèm request.

Access-Control-Allow-Credentials — Khi đặt true, cho phép gửi cookie và Authorization header. Không thể dùng chung với origin *.

Access-Control-Max-Age — Thời gian trình duyệt cache kết quả preflight, giúp giảm số lượng request OPTIONS.

Lỗi CORS Thường Gặp

Dev nào cũng từng đau đầu với lỗi CORS. Mình đã gặp rất nhiều lần, và đây là những nguyên nhân phổ biến nhất:

Server không set header CORS — Quên cấu hình CORS ở backend. Đây là lỗi số một. Trình duyệt chặn vì server không phản hồi với Access-Control-Allow-Origin.

Sai origin — Server chỉ cho phép http://localhost:3000 nhưng frontend chạy ở http://localhost:5173. Một port khác cũng là một origin khác.

Wildcard với credentials — Đặt Access-Control-Allow-Origin: * cùng lúc với Access-Control-Allow-Credentials: true. Trình duyệt từ chối vì lý do bảo mật. Bạn phải chỉ định origin cụ thể.

Thiếu header trong preflight — Client gửi header Authorization nhưng server không khai báo trong Access-Control-Allow-Headers. Preflight thất bại, request bị chặn.

Cách Cấu Hình CORS Phổ Biến

Node.js (Express)

const cors = require('cors');
app.use(cors({
  origin: 'https://myapp.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

Nginx

location /api/ {
    add_header Access-Control-Allow-Origin "https://myapp.com";
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}

WordPress

Thêm vào functions.php hoặc cấu hình ở plugin:

add_action('init', function() {
    header('Access-Control-Allow-Origin: https://myapp.com');
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization');
});

Bảo Mật Với CORS

Nhiều người nghĩ CORS là tính năng bảo mật, nhưng thực ra nó là cơ chế giải phóng hạn chế bảo mật. CORS nới lỏng Same-Origin Policy, nên nếu cấu hình sai, bạn đang tạo lỗ hổng.

Một số nguyên tắc mình luôn tuân thủ:

Không dùng wildcard khi có authentication — Nếu API yêu cầu đăng nhập, phải chỉ định origin cụ thể. * + credentials là công thức cho disaster.

Liệt kê origin tường minh — Tốt hơn là duy trì danh sách các domain được phép, thay vì mở rộng *.

CORS không thay thế authentication — CORS chỉ kiểm soát ở tầng trình duyệt. Ai đó dùng curl hoặc Postman vẫn gọi API được. CORS không phải firewall, đừng nhầm lẫn.

CORS Và Hiệu Năng

Preflight request tạo thêm một HTTP round-trip cho mỗi request phức tạp. Nếu API của bạn nhận hàng nghìn request mỗi phút, số lượng preflight có thể ảnh hưởng đến hiệu năng.

Giải pháp là dùng Access-Control-Max-Age để cache preflight. Trình duyệt sẽ không gửi lại request OPTIONS trong khoảng thời gian này. Đặt giá trị cao (như 3600 giây) giúp giảm tải đáng kể.

Kiểm Tra CORS Như Thế Nào?

Cách nhanh nhất là mở DevTools (F12), vào tab Network. Gửi request và xem có request OPTIONS (preflight) trước không. Response headers có chứa các Access-Control-* header hay không.

Ngoài ra, công cụ như curl rất hữu ích để test CORS từ terminal:

curl -H "Origin: https://myapp.com" \
  -H "Access-Control-Request-Method: POST" \
  -X OPTIONS \
  https://api.example.com/data

Kết quả sẽ hiển thị các CORS header mà server trả về, giúp bạn debug nhanh.

Kết Luận

CORS là phần không thể thiếu trong phát triển web hiện đại. Hiểu đúng cách hoạt động giúp bạn tránh được hàng tá lỗi khó chịu và cấu hình bảo vệ ứng dụng thay vì tạo lỗ hổng. Quy tắc vàng: chỉ cho phép những origin thực sự cần thiết, luôn set credentials một cách có ý thức, và nhớ rằng CORS bảo vệ người dùng, không bảo vệ server của bạn.

ThienLv

Mình là Thien, người tạo ra blog này. Ban ngày làm marketing, ban đêm cày tiền online và chơi với AI. Blog này là nơi mình ghi lại những gì mình thử qua — tool nào xịn, chiến thuật nào chạy được, cái gì thất bại. Mình không giỏi nhất, nhưng mình thích chia sẻ thật. Chill với một ly cafe đá là lý tưởng nhất.

Xem tất cả bài viết →

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *