Ajax クロスドメインリクエスト 制約

2 件のコメント

JavaScript を用いて クロスドメイン で リクエストを行いたいと思うと、 "同一制限元ポリシー(Same Origin Policy)" に引っかかります。 そもそもその制約にある背景は何か…といったところから、制約内容、制約の例外、制約の回避についてまとめました。

制約する理由

クロスサイトリクエストフォージェリ(CSRF)対策。 悪意あるサイトからの不正な要求を拒否するため。

制約の回避方法を見ていてもそうですが、信頼できるサーバーかのリクエストしか受け付けないようになっているようです。

制約の内容 ― 同一生成元ポリシー(Same Origin Policy)

以下の3条件がすべて満たされている場合のみ、XMLHttpRequest によるデータ送信 & 受信が行えます。 それ以外は基本的に通信が拒否されます。

  • スキーム(http / https)が同じ
  • ホスト(サーバー名、IPアドレス)が同じ
  • ポートが同じ

ちなみに パス はどのように変わっても通信できます。

制約の例外 ― 制約されないリソース

以下のリストに挙げる リソース の取得は クロスドメイン制約 を受けません。

  • script タグ による JavaScript リソース の取得。
  • link タグ による CSS リソース の取得。
  • @font-face による webフォント の取得。
  • img タグ による 画像ファイル の取得。
  • video タグ, audio タグ による マルチメディアファイル の取得。
  • object タグ, embed タグ, applet タグ による プラグイン。
  • frame タグ, iframe タグ による 別サイトコンテンツ の取得。

制約の回避 ― Cross-Origin Resource Sharing (CORS)

CORS 仕様 を満たすことで、クロスドメインリクエストを利用できるようになります。 考えるべきは次の 2 + 1 パターンです。

  • GET リクエスト(プリフライト 不要)
  • GET 以外の リクエスト(POST, PUT、DELETE 等)(プリフライト 必要)
  • Cookie 操作 (withCredentials 指定)

(※正確には POST の一部で プリフライト 不要 ですが、特性的に "私は" プリフライトを行った方が良いと考えるので上記のように記載します。)

次のような状況を想定して、具体的にどのようなヘッダーを設定してやりとりするかを以下にまとめます。

GET リクエスト (プリフライト無し)

GET は特に制約なく簡単に回避できます。

  1. サーバーA から クライアント へ WEBコンテンツ を取得
  2. クライアント から サーバーB へのリクエストで追加するヘッダー
    GET
    • Origin: http://servera
  3. サーバーB から クライアント へのレスポンスで追加するヘッダー
    • Access-Control-Allow-Origin: *

POST, PUT, DELETE リクエスト (プリフライト有り)

実通信を始める前に、OPTION で サーバーB と通信を行って許可される通信元であることを確認します。 (=プリフライト) GET 以外 の場合、プリフライトが必要になります。

  1. サーバーA から クライアント へ WEBコンテンツ を取得
  2. クライアント から サーバーB へのリクエスで追加するトヘッダー
    OPTIONS
    • Origin: http://servera
    • Access-Control-Request-Method: POST
    • Access-Control-Request-Headers: X-PINGOTHER
  3. サーバーBからクライアントへのレスポンスで追加するヘッダー
    • Access-Control-Allow-Origin: http://servera
    • Access-Control-Allow-Methods: POST, GET, OPTIONS
    • Access-Control-Allow-Headers: X-PINGOTHER
    • Access-Control-Max-Age: 1728000
  4. クライアント から サーバーB へのリクエストで追加するヘッダー
    POST, PUT, DELETE
    • Origin: http://servera
  5. サーバーB から クライアント へのレスポンスで追加するヘッダー
    • Access-Control-Allow-Origin: http://servera

withCredentials 指定

Cookie 操作を行う場合、レスポンスヘッダーに Access-Control-Allow-Credentials が必要になります。 また、 withCredengials 指定する場合、Access-Control-Allow-Origin: * (ワイルドカード指定)が使えません。 必ずホスト名(サーバー名 または IPアドレス)を指定します。

以下の例では GET メソッド の場合を例に示します。

  1. サーバーA から クライアント へ WEBコンテンツ を取得
  2. クライアント から サーバーB へのリクエストで追加するヘッダー
    • Origin: http://servera
  3. サーバーB から クライアント へのレスポンスで追加するヘッダー
    • Access-Control-Allow-Origin: http://servera
    • Access-Control-Allow-Credentials: true

参考記事

  1. 気になったので…
    URLの最初にあるのはプロトコルではなくスキームです。
    httpスキームとhttpsスキームはどちらもプロトコルとしてhttpを使用するスキームです。
    (httpsというプロトコルはありません)

    返信削除
  2. butakenさん、ご指摘ありがとうございます。
    ご指摘いただいた箇所の修正を行いました。

    URLの構成については、IBMのサイトでご指摘の通り記載をみかけました。
    確かに「カスタムURLスキーム」と言うくらいなので、URLの最初にあるのは"スキーム"ですね。

    まだまだ勉強不足です。。

    返信削除