Trong cuộc điều tra dưới đây dưới dạng API, tôi sử dụng http://example.com thay vì http: // myApiUrl / đăng nhập từ câu hỏi của bạn, vì điều này đầu tiên hoạt động.
Tôi giả sử rằng trang của bạn trên http: //my-site.local: 8088 .
Lý do tại sao bạn thấy kết quả khác nhau là Postman:
- đặt tiêu đề
Host=example.com
(API của bạn)
- KHÔNG đặt tiêu đề
Origin
Điều này tương tự như cách gửi yêu cầu của trình duyệt khi trang web và API có cùng tên miền (trình duyệt cũng đặt mục tiêu đề Referer=http://my-site.local:8088
, tuy nhiên tôi không thấy điều đó trong Postman). Khi Origin
tiêu đề không được đặt, thông thường các máy chủ cho phép các yêu cầu như vậy theo mặc định.
Đây là cách tiêu chuẩn để Postman gửi yêu cầu. Nhưng một trình duyệt gửi các yêu cầu khác nhau khi trang web và API của bạn có các tên miền khác nhau và sau đó CORS xảy ra và trình duyệt tự động:
- đặt tiêu đề
Host=example.com
(của bạn là API)
- đặt tiêu đề
Origin=http://my-site.local:8088
(trang web của bạn)
(Tiêu đề Referer
có cùng giá trị như Origin
). Và bây giờ trong tab Bảng điều khiển & Mạng của Chrome, bạn sẽ thấy:
Khi bạn có Host != Origin
CORS và khi máy chủ phát hiện yêu cầu như vậy, nó thường chặn nó theo mặc định .
Origin=null
được đặt khi bạn mở nội dung HTML từ thư mục cục bộ và nó sẽ gửi yêu cầu. Tình huống tương tự là khi bạn gửi yêu cầu bên trong <iframe>
, như trong đoạn trích dưới đây (nhưng ở đây Host
tiêu đề hoàn toàn không được đặt) - nói chung, ở mọi nơi, đặc tả HTML đều nói nguồn gốc mờ, bạn có thể dịch nó sang Origin=null
. Thông tin thêm về điều này bạn có thể tìm thấy ở đây .
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
Nếu bạn không sử dụng một yêu cầu CORS đơn giản, thông thường trình duyệt cũng tự động gửi yêu cầu TÙY CHỌN trước khi gửi yêu cầu chính - có thêm thông tin ở đây . Đoạn mã dưới đây cho thấy nó:
fetch('http://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)
Bạn có thể thay đổi cấu hình máy chủ của mình để cho phép các yêu cầu CORS.
Dưới đây là một cấu hình ví dụ bật CORS trên nginx (tệp nginx.conf) - hãy cẩn thận với cài đặt always/"$http_origin"
cho nginx và "*"
cho Apache - điều này sẽ bỏ chặn CORS khỏi bất kỳ miền nào.
location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
Đây là một cấu hình ví dụ bật CORS trên Apache (tệp .htaccess)
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests |
# ------------------------------------------------------------------------------
# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"