nginx / chromeを使用したクロスオリジンリソースシェアリング(CORS)


13

次のセグメンテーションを使用したWebサイトがあります。

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

両方を許可しexample.comdevelopers.example.comにAJAXリクエストを送信したいと思いますapi.example.com

api.example.comユニコーンによって提供されているRackアプリであるのためのこれまでの私のnginx設定は、次のようになります。

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

}

私の読書に基づいて、これは私がやろうとしていることに十分なはずです。

OPTIONSの応答:

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仕様によると、複数のオリジンは使用したコンマではなくスペースで区切る必要があるため、このヘッダーを送信してみてください。

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

しかし、Mozillaのドキュメントでは複数の起源については言及されていません。

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

それが機能する場合、許可リストと一致する場合、クライアントによって送信されたヘッダーAccess-Control-Allow-Originの値を含むヘッダーを返すようにnginxまたはアプリケーションサーバーを設定する必要があります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}) これにより、OPTIONSプリフライトがまったく実行されなくなりました。
ジョンレッドベッター

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.