IE10 の CORS for XHR


IE10 Platform Preview 4 では、Cross-Origin Resource Sharing (CORS) (英語) for XMLHttpRequest (XHR) (英語) がサポートされており、これによって、ブラウザーが異なっても同じように動作するクロスサイト シナリオの構築が容易になります。CORS for XHR により、サイト間でシンプルかつ柔軟にデータを共有できます。最も基本的なシナリオでは、CORS により、どのサイトからでもアクセスできるデータ ソースを作成することができますが、簡単な微調整を加えて、許可されたサイトに対する制限、データ変更のサポート、および認証の許可を設定することもできます。最も重要な点は、CORS により、サーバーの参加を要求することで既存サイトの安全性を維持できるということです。

シンプルなクロスオリジン XHR

クロスオリジン XHR 要求と同一オリジン要求を比較してみましょう。スクリプト上の違いは、open メソッドに渡される URL のみです。たとえば、フォト アルバムのリストをフェッチするスクリプトを作成するとします。

従来の XHR

// Script running on http://photos.contoso.com

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "/albums", true);

xhr.send();

ここで、アルバムのリストに、別オリジンからアクセスできるようにします。この場合の別オリジンは、まったく別のドメインでも、同じベース ドメインの別のホストでもかまいません。いずれの場合も、ブラウザーから自動的に CORS 要求が送信されるようにするには、別サイトの完全な URL を指定するだけで十分です。

CORS 対応 XHR

// Script running on http://www.contoso.com

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "http://photos.contoso.com/albums", true);

xhr.send();

サイトで使用する機能検出にこのコードをラップすると、旧バージョンのブラウザーへのフォールバックが可能になります。最良のアプローチは、XHR の CORS サポートに直接関係している "withCredentials" を確認することです。

機能検出を行う CORS 対応 XHR

// Script running on http://www.contoso.com

var xhr = new XMLHttpRequest();

if ("withCredentials" in xhr) {

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "http://photos.contoso.com/albums", true);

xhr.send();

} else {

// Fallback behavior for browsers without CORS for XHR

}

この時点のクライアント コードでは、CORS 要求が直接 "http://photos.contoso.com" に行われていますが、この要求はデータを返すことができません。このエラーが発生するのは、サーバーがまだ参加していないためです。開発者ツールを少し見てみると、何が悪かったのかがわかります。

'Access-Control-Allow-Origin' ヘッダーが見つからなかったことを示す F12 ツールのスクリーンショット

これを見ると、サーバーが応答内で "Access-Control-Allow-Origin" ヘッダーを送信する必要があることがわかります。今回のシナリオでは、アルバムを開くのにどのサイトからでもアクセスできるようにするのではなく、"http://www.contoso.com" からのアクセスのみを有効にします。このためには、どのサイトで要求が発生したのかという情報をサーバーが特定できるようにする必要があります。送信要求を調べると、まさにこの情報が含まれた新しいヘッダー "Origin" が見つかります。

シンプルな CORS 要求ヘッダー

GET http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

...

サーバーはこの情報を使用することで、特定のサイトからのアクセスのみを許可するようにアクセスを制限することができます。サーバーが '*' という値を使用して、常に "Access-Control-Allow-Origin" ヘッダーを追加する場合は、すべてのサイトからのアクセスが許可されます。今回のシナリオでは、サーバー側で要求の発生元を確認してから "Access-Control-Allow-Origin" を設定して "http://www.contoso.com" からのアクセスのみを許可します。

シンプルな CORS 応答ヘッダー

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

...

上のように更新すると、"http://www.contoso.com" クライアントが "http://photos.contoso.com" にあるサーバーのアルバム リストにアクセスできるようになります。

プレフライト要求を送信するクロスオリジン XHR

ここまでで説明したシンプルな CORS 要求は、フォト アルバムのダウンロードのような、読み取りだけの基本的なシナリオに適しています。これを応用して、複数のサイト間でデータを変更できるようにするには、サーバー側でもう少し設定を工夫する必要があります。たとえば、新しいアルバムを作成するためのコードをクライアント側に追加するとします。

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("PUT", "http://photos.contoso.com/albums", true);

xhr.send(JSON.stringify({ name: "New Album" }));

このコードは、そのまま実行しても役に立ちません。ネットワーク トラフィックを調べると、要求は送信されたものの、思っていた内容ではないことがわかります。

OPTIONS プレフライト要求を示している F12 ツールのスクリーンショット

ブラウザーが実際に送信した要求は、プレフライト要求と呼ばれます。プレフライト要求とは、サーバー上でデータを変更する可能性のある要求の前に送信される要求です。このような要求は、CORS 仕様に定義されている、"シンプルでない" プロパティの存在によって特定されます。"シンプルでない" プロパティとは、"PUT" などの特定の HTTP メソッドからカスタムの HTTP ヘッダーまで、さまざまです。ブラウザーはプレフライト要求を送信して、実要求を送信する許可をサーバーに求めます。この例では、"PUT" 要求が許可されるかどうかをブラウザーが確認しています。

プレフライト要求

OPTIONS http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

Access-Control-Request-Method: PUT

...

ブラウザーが実要求を送信できるようにするには、サーバー側にいくつかの変更を加える必要があります。この場合も、開発者ツールを確認して詳しい情報を調べることができます。

'Access-Control-Allow-Methods' リストが見つからなかったことを示す F12 ツールのスクリーンショット

最初にすることは、同じ URL に対する他の要求とは異なるものとして "OPTIONS" プレフライト要求をサーバーに認識させることです。サーバーは、許可された要求元から "Access-Control-Request-Method" により "PUT" 要求が出されていることを確認することでプレフライト要求を検証した後、"Access-Control-Allow-Methods" ヘッダーを介して適切な承認を送信します。

プレフライト応答

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

Access-Control-Allow-Methods: PUT

...

プレフライトが処理されて承認されると、実要求が処理されます。

実要求

PUT http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

...

技術的には、この時点でアルバムの追加が完了しますが、そのことは、サーバーが正しく応答しない限りクライアント コードに伝わりません。具体的には、サーバーの応答内に "Access-Control-Allow-Origin" が含まれている必要があります。

実応答

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

...

これで、クライアントは新しいアルバムをクロスオリジンで追加し、アクションが正常に完了したかどうかを知ることができます。

次のステップ

CORS を他の新しいプラットフォーム機能と組み合わせると、魅力的なシナリオを作成することができます。その一例として、Cross-Site Upload テスト ドライブ (英語) をご紹介します。このプログラムは、CORS、XHR、FileAPI、および Progress イベントを使用して、クロスオリジンのファイル アップロードを追跡するものです。ぜひお試しください。

— Internet Explorer 担当グループ プログラム マネージャー Tony Ross

Skip to main content