logo
GeekFormat

Công cụ kiểm tra CORS

Bảng chẩn đoán CORS

Mô phỏng preflight và yêu cầu thực tế từ phía máy chủ, xác định nhanh chóng vấn đề là do Allow-Origin, Allow-Headers hay credentials.

Mô phỏng CORS preflight và yêu cầu thực từ máy chủ, kiểm tra 6 tiêu đề chính, phát hiện lỗi cấu hình cross-domain chính xác, kèm mẫu code Nginx/Node.js/Spring

Đề xuất Liên quan

Trường hợp sử dụng

  • Khi console trình duyệt báo lỗi No 'Access-Control-Allow-Origin' header, hãy dùng công cụ này ngay để kiểm tra tiêu đề CORS mà giao diện đích thực sự trả về
  • Trong quá trình kết nối dự án frontend-backend tách biệt, kiểm tra xem cấu hình CORS của backend có hoạt động đúng không, tránh mất thời gian sửa chữa mù quáng
  • Sau khi cấu hình Nginx, Apache reverse proxy hoặc API gateway (Kong/APISIX/Spring Cloud Gateway), xác minh quy tắc CORS đã được chuyển tiếp chính xác
  • Khi yêu cầu xuyên miền mang Cookie thất bại, chuyển đổi chế độ credentials để kiểm tra xung đột giữa Allow-Credentials và Allow-Origin
  • Sau khi thêm tiêu đề yêu cầu tùy chỉnh (như X-Token, X-Requested-With) yêu cầu bị chặn, kiểm tra xem đã khai báo chính xác trong Allow-Headers chưa
  • Yêu cầu xuyên miền với phương thức không phải simple method như PUT/DELETE/PATCH thất bại, kiểm tra Allow-Methods có chứa phương thức liên quan không
  • Frontend không thể đọc tiêu đề phản hồi tùy chỉnh (như X-Request-Id, X-Total-Count), kiểm tra cấu hình Access-Control-Expose-Headers
  • Sau khi sử dụng CDN, xuyên miền hoạt động không ổn định, kiểm tra Vary: Origin đã được đặt đúng chưa để tránh CDN lưu đệm sai phản hồi
  • Đối với lỗi xuyên miền thỉnh thoảng xảy ra trong môi trường sản xuất, mô phỏng tình huống sự cố và bảo toàn toàn bộ thông điệp phản hồi để backend kiểm tra
  • Khi học nguyên lý CORS, quan sát tác động của từng tiêu đề thông qua yêu cầu thực để hiểu sâu hơn cơ chế xuyên miền

Tính năng

  • Mô phỏng trực tiếp yêu cầu preflight và yêu cầu thực từ máy chủ, không bị can thiệp bởi bộ đệm và tiện ích mở rộng trình duyệt, kết quả chính xác hơn
  • Hiển thị riêng phản hồi OPTIONS preflight và yêu cầu GET/POST thực, giúp xác định rõ ở bước nào có vấn đề
  • Kiểm tra lần lượt 6 tiêu đề CORS chính: Access-Control-Allow-Origin, Allow-Methods, Allow-Headers, Allow-Credentials, Expose-Headers, Max-Age, mỗi tiêu đề có trạng thái vượt qua/cảnh báo/thất bại riêng
  • Thông minh phát hiện xung đột kinh điển giữa ký tự * và chế độ credentials, tức thời cảnh báo bẫy cấu hình phổ biến
  • Hỗ trợ tùy chỉnh Origin, phương thức HTTP (GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS) và tiêu đề yêu cầu tùy chỉnh
  • Chuyển đổi chế độ gửi credentials (Cookie/tiêu đề Authorization/chứng chỉ khách hàng TLS) để mô phỏng tình huống withCredentials=true
  • Tự động kiểm tra xem tiêu đề Vary: Origin đã được đặt đúng cách chưa, ngăn CDN/reverse proxy lưu đệm phản hồi CORS không chính xác
  • Cấu trúc hiển thị cài đặt Max-Age của preflight cache, đánh giá tác động hiệu năng từ tần suất yêu cầu preflight
  • Kiểm tra cấu hình Access-Control-Expose-Headers, xác nhận những tiêu đề nào JavaScript của frontend có thể đọc
  • Cung cấp hướng dẫn sửa từng dòng, bao gồm mẫu cấu hình cho các framework phổ biến Nginx, Apache, Node.js/Express, Spring Boot, Python/Django/Flask
  • Ghi lại toàn bộ thông điệp thô của yêu cầu và phản hồi, bao gồm mã trạng thái, tất cả tiêu đề phản hồi và mẫu nội dung phản hồi
  • Tự động xác định sự khác biệt giữa simple request và yêu cầu cần preflight, giải thích tại sao yêu cầu của bạn lại kích hoạt OPTIONS preflight
  • Phát hiện sự cố CORS trong tình huống chuyển hướng (Origin có thay đổi sau khi nhảy 301/302/307/308 hay không)
  • Hỗ trợ kiểm tra tình huống nội dung hỗn hợp HTTPS/HTTP, báo cáo sự cố xuyên miền gây ra bởi mixed content

Cách Sử dụng

  1. Nhập địa chỉ đầy đủ của giao diện cần kiểm tra vào ô URL đích (hỗ trợ http/https, phải có đường dẫn)
  2. Nhập Origin thực của trang frontend vào ô Origin yêu cầu (ví dụ https://example.com, phải có giao thức và cổng, không được thêm đường dẫn phía sau)
  3. Chọn phương thức yêu cầu HTTP (GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS), mặc định là GET
  4. Thêm các tiêu đề muốn gửi vào vùng tiêu đề yêu cầu tùy chỉnh, một mục mỗi dòng theo định dạng ví dụ X-Token: abc123. Nếu Content-Type là loại không phải simple type như application/json sẽ tự động kích hoạt preflight
  5. Đánh dấu tùy chọn "Gửi thông tin xác thực" theo tình huống của bạn — phải đánh dấu nếu mã frontend sử dụng withCredentials=true hoặc credentials: 'include' của fetch
  6. Nhấp nút "Bắt đầu kiểm tra", công cụ sẽ lần lượt gửi yêu cầu OPTIONS preflight và yêu cầu thực từ máy chủ (nếu preflight vượt qua hoặc không cần thiết)
  7. Xem báo cáo phân tích: xem đánh giá tổng thể trước, sau đó kiểm tra lần lượt trạng thái từng tiêu đề CORS, điều chỉnh cấu hình máy chủ theo hướng dẫn sửa lỗi, sau đó kiểm tra lại để xác nhận

Câu hỏi Thường gặp

Tại sao Postman/curl yêu cầu bình thường, nhưng trình duyệt truy cập lại báo lỗi xuyên miền?

Đây là sự cố CORS kinh điển nhất! Bởi Postman và curl hoàn toàn không chịu ảnh hưởng của Same-Origin Policy — chúng là ứng dụng khách HTTP, không phải trình duyệt, không chặn phản hồi, cũng không tự động gửi OPTIONS preflight. Lỗi xuyên miền là cơ chế bảo mật riêng của trình duyệt, chỉ môi trường JavaScript của trình duyệt mới kiểm tra CORS. Postman gọi thành công chỉ chứng minh giao diện có thể trả về dữ liệu, không chứng minh CORS chính xác. Bạn cần sử dụng trình duyệt hoặc công cụ này (mô phỏng quy trình CORS phía máy chủ) để kiểm tra

Lỗi CORS là vấn đề frontend hay backend, nên ai sửa?

99% lỗi CORS là vấn đề cấu hình phía backend. Phía frontend có thể làm được rất ít, bản chất CORS là máy chủ cấp quyền cho trình duyệt thông qua tiêu đề. Phía frontend chỉ có thể đặt withCredentials, không thể nào né tránh hạn chế bảo mật. Việc sử dụng proxy của frontend là lừa trình duyệt coi là cùng nguồn gốc, không phải sửa CORS thực sự. Môi trường sản xuất vẫn cần backend cấu hình CORS chính xác

Tại sao GET không xuyên miền, nhưng đổi sang POST/PUT lại xuyên miền?

Bởi GET thường đáp ứng simple request, trình duyệt gửi trực tiếp; còn POST nếu gửi Content-Type: application/json (90% giao diện POST) sẽ không phải simple request, sẽ kích hoạt OPTIONS preflight. Yêu cầu preflight cần tiêu đề CORS chính xác. Nhiều người chỉ cấu hình tiêu đề cho GET/POST mà không xử lý OPTIONS. Bản thân PUT/DELETE/PATCH cũng không phải phương thức đơn giản, chắc chắn cần preflight

Môi trường phát triển giải quyết xuyên miền thế nào? Môi trường sản xuất thì sao?

Môi trường phát triển có nhiều cách: ①proxy tích hợp của framework (devServer.proxy, server.proxy): ủy quyền yêu cầu đến cùng nguồn; ②tắt tham số bảo mật trình duyệt với --disable-web-security, chỉ giới hạn thử nghiệm tại máy; ③backend cấu hình CORS cho phép localhost (đề xuất). Môi trường sản xuất bắt buộc phải backend cấu hình CORS chính xác: danh sách trắng, Allow-Methods/Allow-Headers/Allow-Credentials, Vary: Origin hoặc sử dụng gateway/Nginx quản lý tập trung

Access-Control-Allow-Origin có thể cấu hình nhiều nguồn không?

Không được. Tiêu đề này chỉ có thể có một giá trị, duy nhất là một nguồn cụ thể hoặc *. Trình duyệt sẽ không chấp nhận nhiều nguồn. Cách đúng là: máy chủ duy trì danh sách trắng, mỗi lần nhận yêu cầu đọc Origin, kiểm tra xem có trong danh sách trắng không, nếu có thì trả về Access-Control-Allow-Origin là chính giá trị Origin đó, đồng thời Vary: Origin. Đừng cố trả về nhiều tiêu đề hoặc phân cách bằng dấu phẩy

Yêu cầu OPTIONS preflight có cần trả về logic nghiệp vụ không? Có thể trả về 204 trực tiếp không?

OPTIONS preflight không cần trả về bất kỳ logic nghiệp vụ và nội dung nào, chỉ cần tiêu đề CORS chính xác và 200/204 là đủ. Cách thực hành tốt nhất là: chặn OPTIONS trực tiếp tại Nginx/gateway, trả về 204 No Content và tiêu đề CORS chính xác, không cần chuyển tiếp đến backend, giảm tải và tránh 405. Nhưng phải đảm bảo tiêu đề CORS của OPTIONS nhất quán với yêu cầu thực

Tại sao đặt withCredentials: true rồi Cookie vẫn không được gửi?

Yêu cầu xuyên miền mang Cookie cần đáp ứng ba điều kiện: ①withCredentials=true hoặc credentials: 'include'; ②Allow-Credentials: true; ③Allow-Origin phải là nguồn gốc cụ thể (không được *). Thiếu một cũng không được. Ngoài ra Cookie phải đặt SameSite=None; Secure (HTTPS) mới có thể gửi xuyên miền; SameSite=Lax/Strict sẽ không mang; thuộc tính Domain phải chính xác; cũng cần lưu ý chính sách Cookie của bên thứ ba

CORS và CSRF có mối quan hệ gì? Cấu hình CORS có gây ra lỗ hổng CSRF không?

CORS là nới lỏng hạn chế xuyên miền, CSRF là tấn công giả mạo yêu cầu xuyên trang, hai khái niệm khác nhau. Cấu hình CORS đúng cách sẽ không trực tiếp gây ra CSRF — CORS chỉ cho phép JS đọc phản hồi, còn CSRF là kẻ tấn công dụ người dùng gửi yêu cầu không hay biết, những yêu cầu này dù không có CORS cũng sẽ được gửi kèm Cookie. Phòng chống CSRF cần dùng CSRF Token, SameSite Cookie, kiểm tra Origin/Referer, đừng phòng CSRF bằng cách tắt CORS. Nhưng nếu Allow-Origin là * và cho phép credentials sẽ mở rộng rủi ro CSRF, vì vậy khi gửi credentials tuyệt đối không được dùng *

Tải tệp, chuyển hướng, tải thẻ img/script có vấn đề CORS không?

Tải tài nguyên bằng <img>, <script>, <link> thông thường không gặp sự cố CORS, là "tài nguyên nhúng" không phải AJAX, trình duyệt cho phép tải nhưng JS không thể đọc nội dung. Nhưng nếu muốn sử dụng Canvas xử lý hình ảnh xuyên miền hoặc dùng fetch/XHR đọc nội dung thì cần CORS và thêm thuộc tính crossorigin. Tải tệp xuyên miền không cần CORS. Chuyển hướng sẽ ảnh hưởng đến CORS: nếu OPTIONS trả về 3xx trình duyệt sẽ từ chối trực tiếp (Preflight redirect not allowed)

Nginx cấu hình CORS thế nào cho đúng? Cho xin mẫu cấu hình hoạt động được?

Điểm chính: ①sử dụng map đối sánh Origin danh sách trắng, đặt $cors_origin động; ②OPTIONS trả về 204 trực tiếp không chuyển tiếp; ③add_header phải thêm always để đảm bảo phản hồi lỗi cũng có tiêu đề; ④thêm Vary: Origin; ⑤cấu hình đúng Allow-Methods/Allow-Headers/Credentials. Mẫu cấu hình có thể tìm thấy trong hướng dẫn sửa lỗi của công cụ này. Cho Nginx, Apache, Node.js Express, Spring Boot, Flask/Django, Koa, Go Gin chúng tôi đều có mẫu đã được kiểm chứng

Sau khi cấu hình CORS làm sao xác nhận nó hoạt động?

Các bước xác nhận: ①trước tiên sử dụng công cụ này kiểm tra trực tuyến; ②mở DevTools Network, đánh dấu Disable cache, kích hoạt yêu cầu, kiểm tra tiêu đề OPTIONS và yêu cầu thực; ③xem Console có lỗi không; ④kiểm tra các tình huống khác nhau: GET không tiêu đề, POST dạng application/json, PUT/DELETE, có/không Cookie, có tiêu đề tùy chỉnh; ⑤sử dụng curl mô phỏng OPTIONS: curl -i -X OPTIONS -H "Origin: https://sourcecuaban.com" https://api.example.com/endpoint

Tại sao yêu cầu xuyên miền lại lỗi trên Chrome nhưng Safari/Firefox lại bình thường? Hoặc ngược lại?

Các trình duyệt khác nhau có sự khác biệt trong chi tiết CORS: ①Safari giới hạn Max-Age nghiêm ngặt hơn, chính sách Cookie (ITP) cũng nghiêm ngặt hơn; ②Chrome kiểm tra ký tự đại diện khi gửi credentials nghiêm ngặt hơn, không cho phép *; ③IE11 dùng XDomainRequest thay vì XMLHttpRequest có nhiều hạn chế; ④xử lý Vary, chuyển hướng, tiêu đề bảo mật có khác biệt tinh tế. Cách khắc phục là cấu hình nghiêm ngặt theo quy định, đừng dựa vào hành vi của một trình duyệt nào

Access-Control-Max-Age nên đặt bao nhiêu? Đặt quá dài hoặc quá ngắn có vấn đề gì?

Đề xuất 3600 (1 giờ) đến 86400 (24 giờ). Quá ngắn (60 giây): bộ đệm hết nhanh, gửi OPTIONS thường xuyên, tăng thời gian và tải máy chủ. Quá dài (một năm): sau khi cập nhật cấu hình bộ đệm cũ có thể còn lâu, khiến cấu hình mới không hoạt động. Chrome/Firefox tự động cắt giá trị vượt quá 86400 xuống 86400. Môi trường phát triển có thể đặt -1 tắt đệm để thuận tiện debug

WebSocket có vấn đề xuyên miền không? CORS áp dụng cho WebSocket không?

WebSocket (ws:// và wss://) không chịu ảnh hưởng từ cơ chế CORS của HTTP, vì là giao thức độc lập. Nhưng giai đoạn bắt tay là yêu cầu HTTP, máy chủ có thể kiểm tra Origin để quyết định cho phép kết nối — đây là kiểm soát quyền ở cấp độ WebSocket, không phải CORS tiêu chuẩn, nhưng nguyên tắc tương tự. Nếu WebSocket bị từ chối cần kiểm tra cấu hình kiểm tra Origin của máy chủ WebSocket, không phải tiêu đề CORS của HTTP

Kết quả kiểm tra của công cụ này có nhất quán với trình duyệt không? Tại sao công cụ vượt qua nhưng trình duyệt vẫn lỗi?

Công cụ này mô phỏng quy trình preflight và yêu cầu thực theo quy định W3C CORS nghiêm ngặt phía máy chủ, logic về cơ bản nhất quán với trình duyệt hiện đại. Nếu công cụ vượt qua nhưng trình duyệt vẫn lỗi, nguyên nhân có thể: ①trình duyệt lưu đệm kết quả cũ, thử Ctrl+F5 làm mới hoặc xóa bộ đệm; ②tiện ích mở rộng trình duyệt sửa đổi hoặc chặn yêu cầu; ③các cài đặt điền trong công cụ không nhất quán với những gì frontend thực sự gửi; ④bộ đệm nút CDN/proxy không nhất quán; ⑤trình duyệt có chính sách bảo mật đặc biệt (nội dung hỗn hợp, hạn chế file://)

术语表

CORS (Cross-Origin Resource Sharing)
Cơ chế bảo mật trình duyệt do W3C quy định, cho phép máy chủ khai báo nguồn gốc nào có quyền truy cập tài nguyên nào, bằng cách thêm một tập hợp tiêu đề phản hồi bắt đầu bằng Access-Control- ở cấp độ giao thức HTTP
Same-Origin Policy (Chính sách cùng nguồn gốc)
Một trong những cơ chế bảo mật cốt lõi của trình duyệt, mặc định cấm JavaScript gửi yêu cầu HTTP đến máy chủ khác nguồn gốc để ngăn trang độc hại đọc dữ liệu nhạy cảm từ trang web khác
Yêu cầu Preflight (Preflight Request)
Trước khi gửi yêu cầu xuyên miền có thể ảnh hưởng đến dữ liệu máy chủ, trình duyệt sẽ gửi trước một yêu cầu OPTIONS để hỏi máy chủ, máy chủ phải phản hồi với tiêu đề CORS chính xác thì trình duyệt mới gửi yêu cầu thực
Simple Request (Yêu cầu đơn giản)
Yêu cầu đáp ứng tất cả điều kiện: phương thức là GET/HEAD/POST, Content-Type chỉ là text/plain/multipart/form-data/application/x-www-form-urlencoded, không có tiêu đề yêu cầu tùy chỉnh, sẽ được gửi trực tiếp không cần gửi OPTIONS preflight
Access-Control-Allow-Origin (ACAO)
Tiêu đề CORS quan trọng nhất, chỉ định nguồn gốc được phép truy cập tài nguyên, giá trị có thể là * hoặc nguồn gốc cụ thể, khi gửi thông tin xác thực không được dùng *
Access-Control-Allow-Methods (ACAM)
Tiêu đề phản hồi preflight, chỉ định tất cả các phương thức HTTP mà máy chủ hỗ trợ, phân cách bằng dấu phẩy, phải khai báo tất cả các phương thức được sử dụng
Access-Control-Allow-Headers (ACAH)
Tiêu đề phản hồi preflight, chỉ định tất cả các tiêu đề yêu cầu được phép, khi yêu cầu có tiêu đề tùy chỉnh phải khai báo ở đây
Access-Control-Allow-Credentials (ACAC)
Chỉ định có cho phép gửi thông tin xác thực trong yêu cầu xuyên miền hay không, giá trị phải là true viết thường
Access-Control-Max-Age (ACMA)
Chỉ định thời gian kết quả preflight có thể được lưu đệm (đơn vị giây), giảm yêu cầu OPTIONS lặp lại không cần thiết
Vary: Origin
Tiêu đề phản hồi báo cho CDN/reverse proxy biết tiêu đề Origin ảnh hưởng đến nội dung phản hồi, bắt buộc phải có khi trả về Allow-Origin động
CORS-safelisted request headers (Tiêu đề yêu cầu được CORS chấp thuận)
Các tiêu đề cơ bản CORS cho phép mặc định không cần khai báo trong Allow-Headers, bao gồm Accept, Accept-Language, Content-Language, Content-Type (chỉ một số loại nhất định)
Forbidden header name (Tên tiêu đề bị cấm)
Các tiêu đề trình duyệt cấm JavaScript tự đặt như Host, Connection, Cookie, Origin v.v. do trình duyệt tự kiểm soát
Credentialed Request (Yêu cầu gửi thông tin xác thực)
Yêu cầu xuyên miền gửi thông tin xác thực danh tính như withCredentials=true hoặc credentials: 'include', sẽ mang theo Cookie và tiêu đề Authorization
Access-Control-Expose-Headers
Chỉ định các tiêu đề phản hồi được phép JavaScript đọc, ngoài các tiêu đề cơ bản được tiết lộ mặc định
Phương thức OPTIONS
Phương thức HTTP dùng để hỏi khả năng của máy chủ, trong CORS trình duyệt dùng phương thức này tự động gửi preflight request
Tiêu đề Origin
Tiêu đề yêu cầu do trình duyệt tự động thêm, chỉ định nguồn gốc của trang web gửi yêu cầu, máy chủ dùng giá trị này để quyết định cho phép hay không
Thuộc tính crossorigin
Thuộc tính HTML chỉ định cách xử lý yêu cầu xuyên miền khi tải tài nguyên, bắt buộc khi sử dụng Canvas xử lý hình ảnh xuyên miền
Chế độ yêu cầu no-cors
Chế độ đặc biệt của API fetch, chỉ có thể gửi simple request và JavaScript không thể đọc phản hồi (opaque response)

Bảng so sánh tiêu đề phản hồi CORS

Bảng quyết định yêu cầu nào sẽ kích hoạt Preflight

Bảng tóm tắt lỗi CORS phổ biến và cách khắc phục

Troubleshooting