Chia sẻ tài nguyên nguồn gốc chéo (CORS) với nginx / chrome


13

Tôi có một trang web với phân khúc sau:

api.example.com 
developers.example.com 
example.com

Tôi muốn cho phép cả hai example.comdevelopers.example.comthực hiện các yêu cầu AJAX api.example.com.

Cấu hình nginx của tôi cho đến nay api.example.com, đó là một ứng dụng Rack đang được phục vụ bởi kỳ lân, trông như thế này:

upstream app_server {
  server unix:/tmp/api.example.com.sock fail_timeout=0;
}

server {
       listen 80;
       server_name api.example.com;
       access_log /home/nginx/api.example.com/log/access.log;
       error_log /home/nginx/api.example.com/log/error.log;
       location / {
         add_header 'Access-Control-Allow-Origin' 'http://example.com,http://developers.example.com';
         add_header 'Access-Control-Allow-Credentials' 'true';
         add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
         add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';

         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_redirect off;
         proxy_pass http://app_server;
       }

}

Dựa trên bài đọc của tôi, điều này là đủ cho những gì tôi đang cố gắng làm.

Các OPTIONS phản hồi:

HTTP/1.1 200 OK
Server: nginx/0.7.67
Date: Sat, 28 Apr 2012 17:20:08 GMT
Content-Type: application/json
Connection: close
Status: 200 OK
Content-Length: 0
Access-Control-Allow-Origin: http://developers.example.com,http://example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type,Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE

Nhưng khi tôi thử các thao tác sau trong bảng điều khiển Chrome:

$.ajax("http://api.example.com", {
  type: 'get',
  contentType: "application/json",
  accept: "application/json"
}).success(function(data){
  console.log("success!", data);
}).fail(function(jqxhr, statusText){
  console.log("fail!", jqxhr, statusText);
})

Tôi hiểu rồi:

XMLHttpRequest cannot load http://api.example.com/. Origin
http://developers.example.com is not allowed by Access-Control-Allow-Origin.

Và tương tự cho http://example.com .

Tôi đang thiếu gì?

Nếu tôi đặt Access-Control-Allow-Originđể *sau đó tôi thấy:

HTTP/1.1 200 OK
Server: nginx/0.7.67
Date: Sat, 28 Apr 2012 17:28:41 GMT
Content-Type: application/json
Connection: close
Status: 200 OK
Content-Length: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE

Nhưng yêu cầu jQuery vẫn thất bại, với chrome cũng nhấn mạnh rằng chuyến bay trước OPTIONSkhông thành công (mặc dù nó đã trả về 200 OK).

Câu trả lời:


17

Theo thông số kỹ thuật của CORS, nhiều nguồn gốc nên được phân tách bằng dấu cách, không phải dấu phẩy như bạn đã sử dụng, vì vậy hãy thử gửi tiêu đề này:

Access-Control-Allow-Origin: http://developers.example.com http://example.com

Các tài liệu Mozilla không đề cập đến nhiều nguồn gốc mặc dù, vì vậy nếu mà vẫn không hoạt động thử chỉ gửi:

Access-Control-Allow-Origin: http://developers.example.com

Nếu nó hoạt động, bạn sẽ cần định cấu hình nginx hoặc máy chủ ứng dụng của bạn để trả về một Access-Control-Allow-Origintiêu đề chứa giá trị của Origintiêu đề được gửi bởi khách hàng nếu nó phù hợp với danh sách được phép. Một cái gì đó giống như cấu hình nginx sau (chưa được kiểm tra) có thể làm điều đó:

if ($http_origin ~ "^(http://developers.example.com|http://example.com)$") {
    add_header "Access-Control-Allow-Origin" $http_origin;
}

Đây là một phần của những gì tôi đã làm. Tôi cũng đã xóa Access-Control-Allow-Headertiêu đề và sửa đổi cuộc gọi jQuery của mình như vậy: $.ajax("http://api.example.com", { type: 'get', crossDomain: true}) Điều đó ngăn cản ánh sáng OPTIONStrước xảy ra.
John Ledbetter

1
LƯU Ý: Nếu giải pháp đã cho không phù hợp với bạn, hãy đọc cái nàycái này . Nó khai sáng, và bạn có thể tìm thấy lý do nó không hoạt động.
it_me

4

Sử dụng ifmột locationkhối trong cấu hình nginx như thế này:

if ($http_origin ~ "^(http://developers.example.com|http://example.com)$") {
    add_header "Access-Control-Allow-Origin" $http_origin;
}

Nguyên nhân nginx làm những điều kỳ lạ. Cụ thể, proxy_passtry_fileskhông làm việc như mong đợi. Xem http://wiki.nginx.org/ IfIsEvil để biết thêm thông tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.