การแชร์ทรัพยากรข้ามแหล่งกำเนิด (CORS) ด้วย nginx / chrome


13

ฉันมีเว็บไซต์ที่มีการแบ่งกลุ่มดังต่อไปนี้:

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

ผมอยากจะช่วยให้ทั้งสองexample.comและdevelopers.example.comจะทำให้การร้องขอ AJAX api.example.comเพื่อ

การกำหนดค่า nginx ของฉันจนถึงตอนapi.example.comนี้ซึ่งเป็นแอป Rack ที่ให้บริการโดยยูนิคอร์นดูเหมือนว่า:

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;
       }

}

จากการอ่านของฉันนี่น่าจะเพียงพอสำหรับสิ่งที่ฉันพยายามจะทำ

การตอบสนองตัวเลือก :

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

แต่เมื่อฉันลองทำสิ่งต่อไปนี้ในคอนโซล 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);
})

ฉันเห็น:

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

และเช่นเดียวกันสำหรับhttp://example.com

ฉันกำลังคิดถึงอะไร

ถ้าผมตั้งAccess-Control-Allow-Originไป*แล้วฉันจะดู:

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

แต่คำขอ jQuery ยังคงล้มเหลวด้วย Chrome ยังเน้นว่าการบินล่วงหน้าOPTIONSล้มเหลว (แม้ว่าจะส่งคืน200 OK)

คำตอบ:


17

ตามCORS specหลายต้นกำเนิดควรคั่นด้วยช่องว่างไม่ใช่จุลภาคตามที่คุณใช้ดังนั้นลองส่งหัวข้อนี้:

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

เอกสาร Mozillaไม่ได้พูดถึงต้นกำเนิดหลายแม้ว่าดังนั้นหากที่ยังไม่ทำงานเพียงพยายามส่ง:

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

หากใช้งานได้คุณจะต้องกำหนดค่า nginx หรือเซิร์ฟเวอร์แอปพลิเคชันของคุณเพื่อส่งคืนAccess-Control-Allow-Originส่วนหัวที่มีค่าOriginส่วนหัวที่ลูกค้าส่งมาหากตรงกับรายการที่อนุญาต สิ่งที่ชอบการกำหนดค่า nginx (ยังไม่ทดลอง) ต่อไปนี้สามารถทำได้:

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

นี่เป็นส่วนหนึ่งของสิ่งที่ฉันทำลงไป ฉันยังลบAccess-Control-Allow-Headerส่วนหัวและแก้ไขการโทร jQuery ของฉันเช่น: $.ajax("http://api.example.com", { type: 'get', crossDomain: true}) ซึ่งป้องกันOPTIONSpreflight ไม่ให้เกิดขึ้นเลย
John Ledbetter

1
หมายเหตุหากการแก้ปัญหาที่ได้รับไม่ได้ทำงานให้คุณอ่านนี้และนี้ มันเป็นความสว่างและคุณอาจพบเหตุผลที่มันไม่ทำงาน
its_me

4

ใช้ifในlocationบล็อกในการกำหนดค่า nginx ดังนี้:

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

ทำให้ nginx ทำสิ่งแปลก ๆ โดยเฉพาะproxy_passและtry_filesไม่ทำงานตามที่คาดไว้ ดูhttp://wiki.nginx.org/IfIsEvilสำหรับข้อมูลเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.