web-dev-qa-db-ja.com

CORS:ブラウザーがOPTIONSプリフライトリクエストを送信しないのはなぜですか?

[〜#〜] cors [〜#〜] について読んだことから、次のように動作するはずだと理解しています。

  1. クライアント側のスクリプトは、サーバーから異なるオリジンリソースの取得を試みます。
  2. ブラウザはこのリクエストをインターセプトし、最初にpreflight OPTIONS requestを同じURLに送信します。
  3. このプリフライトリクエストに対するresponse適切なヘッダーが含まれている場合(例:Access-Control-Allow-Origin: *)、ブラウザはメインリクエストの送信が許可されていることを理解して実行します。
  4. 応答がクライアントスクリプトに返されます。

次のようなテストを設定しました。

  • goのサーバーは、GET要求とOPTIONS要求(CURLを使用してチェック)の両方を受け入れ、_Access-Control-*応答のヘッダー
  • 次のスクリプトを含む単純なHTMLページ(別のポート上の別のサーバーによって提供される)($はjQueryを表します):

    $.ajax({
      type: "GET",
      crossDomain: true,
      url: "http://local.site.com/endpoint,
      success: function (data) {
        alert(data);
      },
      error: function (request, error) {
        alert(error);
      }
    });
    

ただし、このメソッドを呼び出すと、[ネットワーク]タブにChrome 49とFirefox 33の両方で、GETが1つだけ表示され、プリフライトOPTIONSリクエストが表示されません。

ChromeからのGETリクエストの詳細は次のとおりです。

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Connection:keep-alive
Host:local.adform.com
Origin:http://localhost:7500
Referer:http://localhost:7500/test-page.html
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36

および対応する応答:

Access-Control-Allow-Headers:Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin:*
Content-Length:2
Content-Type:text/plain; charset=utf-8
Date:Wed, 03 Aug 2016 10:53:19 GMT

why my browser(s)プリフライトリクエストを送信しない

19
ffriend

コメンテーターが指摘したように、GETでブラウザーは常にプリフライトOPTIONSリクエストを送信するとは限りません。プリフライトが実際に必要な場合、ブラウザに送信させる方法の1つは、カスタムヘッダー(たとえば、「X-PINGOVER:pingpong」など)を設定することです。サーバーは、「Access-Control-Allow-Headers」応答ヘッダーに追加して、このリクエストヘッダーも許可する必要があることに注意してください。


私の基本的な目標は、ドメインa.comを使用してcookiesa.comのサーバーに渡すことでしたが、別のサイトのページからb.com(これは、サードパーティのウェブサイトでユーザーを追跡しています)。リクエストと一緒にCookieを送信するには、もう少し作業が必要です。

クライアント側(つまりJavaScript)では、クロスドメインリクエストを有効にし、資格情報の受け渡しを許可する必要があります。例えば。 jQueryを使用した次のリクエストがうまくいきました。

$.ajax({
  type: "GET",
  url: "http://example.com",
  xhrFields: {
    withCredentials: true           // allow passing cookies
  },
  crossDomain: true,                // force corss-domain request                
  success: function (data) { ... },
  error: function (request, error) { ... }
});

サーバー側1つの応答ヘッダーを設定する必要があります。

  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin: <requester Origin>

ここで、<requester Origin>は、プロトコル+ホスト+呼び出しを実行したWebサイトのポートです。一般的な*は多くのブラウザでは機能しない可能性があるため、サーバーがリクエストのRefererヘッダーを解析し、許可された特定のOriginで応答することは意味があります。

12
ffriend