Nguyễn Đình Cường
0 comment
09 Nov, 2026
Bạn gọi API từ giao diện và nhận về dòng chữ đỏ "has been blocked by CORS policy". Phản xạ đầu tiên của nhiều người là tìm cách tắt nó đi bằng mọi giá. Hiểu CORS thực sự là gì sẽ giúp bạn sửa đúng chỗ mà vẫn giữ được an toàn.
Trình duyệt có chính sách bảo mật cơ bản gọi là same-origin: mã JavaScript trên một nguồn (origin) không được tự do đọc phản hồi từ nguồn khác. Một origin gồm ba phần: giao thức, tên miền và cổng. Ví dụ https://app.example.com và https://api.example.com là hai origin khác nhau, http://localhost:3000 và http://localhost:8000 cũng vậy.
Chính sách này bảo vệ bạn: nếu không, một trang xấu bạn vừa mở có thể dùng phiên đăng nhập sẵn có để đọc dữ liệu cá nhân từ ngân hàng của bạn.
CORS (Cross-Origin Resource Sharing) cho phép server tuyên bố rõ nguồn nào được phép đọc phản hồi của nó, thông qua các header. Điều cần nhớ: CORS được thực thi bởi trình duyệt, và cấu hình nằm ở server API, không phải ở client. Request vẫn có thể tới server và được xử lý, nhưng trình duyệt sẽ chặn không cho JavaScript đọc kết quả nếu header không cho phép.
Access-Control-Allow-Origin: https://app.example.comAccess-Control-Allow-Methods: GET, POST, PUT, DELETEAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Max-Age: 600Với các request "không đơn giản" (dùng phương thức như PUT, DELETE, hoặc header tùy chỉnh như Authorization, hoặc Content-Type: application/json), trình duyệt tự gửi trước một request OPTIONS để hỏi "tôi có được phép gửi request này không?". Server phải trả lời với các header cho phép (mã 204 hoặc 200). Nếu preflight thất bại, request thật không được gửi đi. Access-Control-Max-Age cho phép trình duyệt nhớ kết quả trong một thời gian để đỡ hỏi lại.
// Expressconst cors = require('cors');app.use(cors({ origin: ['https://app.example.com'], methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'],}));# FastAPIfrom fastapi.middleware.cors import CORSMiddlewareapp.add_middleware( CORSMiddleware, allow_origins=["https://app.example.com"], allow_methods=["*"], allow_headers=["*"],)// Laravel: config/cors.php'paths' => ['api/*'],'allowed_origins' => ['https://app.example.com'],'allowed_methods' => ['*'],'allowed_headers' => ['*'],'supports_credentials' => false,Nếu cần gửi cookie qua origin khác, client phải bật credentials: 'include' (fetch) và server phải trả Access-Control-Allow-Credentials: true. Khi đó không được dùng dấu sao * cho Allow-Origin; phải chỉ rõ origin cụ thể. Đây là nguồn gây lỗi thường gặp.
* với credentials: trình duyệt từ chối.Tiện ích trình duyệt "tắt CORS" hay cho phép mọi origin bằng * trên API có dữ liệu riêng tư là những lối tắt nguy hiểm. Trong phát triển, cách gọn gàng là dùng proxy của dev server (ví dụ Vite hay Next.js) để request đi qua cùng origin, hoặc cho phép riêng origin localhost ở môi trường dev. Ở production, chỉ cho phép đúng các origin cần thiết. Lưu ý CORS không thay thế xác thực: ai không phải trình duyệt vẫn gọi được API của bạn, nên vẫn phải kiểm tra quyền ở server.
Khi gặp lỗi, đừng đoán. Hãy mở tab Network của trình duyệt, tìm request OPTIONS và request thật. Kiểm tra mã trạng thái của preflight, các header Access-Control-* trong phản hồi, và so sánh giá trị origin trình duyệt gửi với giá trị server cho phép. Thử gọi cùng endpoint bằng công cụ như curl để xác nhận server hoạt động bình thường; nếu curl chạy được mà trình duyệt bị chặn, vấn đề gần như chắc chắn nằm ở header CORS. Làm theo thứ tự này giúp bạn khoanh vùng nhanh và tránh sửa nhầm chỗ.
Hãy luôn kiểm tra lại bằng thực hành thay vì chỉ đọc lý thuyết: dựng một dự án nhỏ, cố tình tạo lỗi, quan sát log và công cụ gỡ lỗi, rồi sửa. Hãy thử cố tình gọi API từ một origin không được phép để tận mắt thấy trình duyệt chặn, và xem các header trong tab Network.
CORS là lớp bảo vệ của trình duyệt, được nới lỏng có chủ đích bởi server. Khi gặp lỗi, hãy xem origin, phương thức, header, preflight và credentials, theo thứ tự đó. Hiểu quy trình này, bạn sẽ sửa lỗi CORS trong vài phút thay vì vài giờ.
Nếu muốn luyện tập cùng bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn sẵn sàng.
Nguyễn Đình Cường
0 comment