すべてのプロダクト
Search
ドキュメントセンター

:CORS (Cross-Origin Resource Sharing)

最終更新日:Dec 22, 2023

同一生成元ポリシー

クロスオリジンアクセス、もしくはJavaScript のクロスオリジンは、セキュリティを考慮したブラウザーの制限の一種であり、すなわち同一生成元ポリシーです。 Web サイト A がその Web ページ上の JavaScript コードを使用して Web サイト B にアクセスしようとすると、A と B は異なるオリジンの 2 つのWebサイトであるため、アクセスはブラウザーによって拒否されます。

ただし、クロスオリジンアクセスは、日常的かつ一般的に使用されています。たとえば、Web サイト www.a.com のバックエンドでは OSS が使用されています。 JavaScript ベースのアップロード機能が Web ページ上で提供されています。 ただし、Web ページ上のリクエストは www.a.com にのみ送信され、他の Web サイトに送信されたリクエストはすべてブラウザーによって拒否されます。 結果として、ユーザーがアップロードしたデータは www.a.com を通じて他のサイトに中継される必要があります。 クロスオリジンアクセスが設定されている場合、データは www.a.com を通じて中継されるのではなく、OSS に直接アップロードされます。

CORS の概要

CORS は、HTML5 によって提供される標準的なクロスオリジンソリューションです。 CORS 規則の詳細については、「W3C CORS Norms」をご参照ください。

CORS は、一連の制御ポリシーであり、相互連携のため HTTP ヘッダーを使用するブラウザーが使用されます。 クロスオリジンリクエストとして開始されたリクエストを識別すると、ブラウザーはオリジンヘッダーを HTTP リクエストに追加し、そのリクエストをサーバーに送信します。 上記の例では、オリジンヘッダーは www.a.com です。リクエストを受信した後、サーバーは指定の規則に基づいてリクエストを許可するかどうかを判断します。 リクエストが許可されると、サーバーは Access-Control-Allow-Origin ヘッダーを応答にアタッチします。 ヘッダーには www.a.com が含まれており、クロスオリジンアクセスが許可されていることを示します。 サーバーがすべてのクロスオリジンリクエストを許可する場合は、Access-Control-Allow-Origin ヘッダーを "*" に設定します。 ブラウザーは、対応するヘッダーが返さるかどうかに基づき、クロスオリジンリクエストが成功しているかどうかを判断します。 対応するヘッダーがアタッチされていない場合、ブラウザーはリクエストをブロックします。これはシンプルな記述です。

上記の内容はシンプルなシナリオです。 CORS 規格では、リクエストを 2 つのタイプに分類します。簡易リクエストと事前確認リクエストです。 事前確認は、許可されていないリクエストがリソースを変更するのを防ぐ保護メカニズムです。 実際のリクエストを送信する前に、ブラウザーは OPTIONS HTTP リクエストを送信し、サーバーがクロスオリジンリクエストを許可するかどうかを判断します。 リクエストが許可されていない場合、ブラウザーは実際のリクエストを拒否します。

次の両方の条件が満たされる場合に限り、事前確認リクエストは必要ありません。

  • リクエストメソッドは以下のいずれかです。

    • GET
    • HEAD
    • POST
  • すべてのヘッダーは以下のリスト内にあります。

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma

事前確認リクエストは、サーバーへの後に続くリクエストに関する情報を提供します。

  • オリジン: オリジン情報をリクエストします。
  • Access-Control-Request-Method: 後に続くリクエストのタイプ。たとえば、POST や GET などがあります。
  • Access-Control-Request-Headers: 明示的に設定されていて後に続くリクエストに含まれるヘッダーのリスト。

事前確認リクエストを受信した後、サーバーはアタッチ情報に基づき、クロスオリジンリクエストを許可するかどうかを判断します。 返された情報は、以下のヘッダーを使用することでも送信されます。

  • Access-Control-Allow-Origin: クロスオリジンリクエストに対して許可されているオリジンのリスト。
  • Access-Control-Allow-Methods: 許可されているクロスオリジンリクエストメソッドのリスト。
  • Access-Control-Allow-Headers: 許可されているクロスオリジンリクエストヘッダーのリスト。
  • Access-Control-Expose-Headers: JavaScript コードへの公開を許可されているヘッダーのリスト。
  • Access-Control-Max-Age: 最大ブラウザーキャッシュ時間 (秒)。

返された情報に基づき、ブラウザーは実際のデータを送信するかどうかを判断します。 上記の各ヘッダーがどれも受信されない場合、ブラウザーは後に続くリクエストを拒否します。

説明 上記の操作はブラウザーによって自動的に実行されるので、詳細については無視してかまいません。 サーバーが正しく構成されていれば、クロスオリジン以外のリクエストの場合でも同一のプロセスになります。
シナリオ

アクセス許可制御はサーバーではなくブラウザーに適用されます。CORS はブラウザーが使用されるシナリオでのみ適用可能です。 そのため、他のクライアントを使用するときは、クロスオリジンの問題について心配する必要はありません。

CORS を主に使用するアプリケーションは、トラフィックをアプリケーションサーバー経由でリダイレクトするのではなく、ブラウザーで Ajax を使用して OSS に直接アクセスします。 これはアップロードおよびダウンロードプロセスに適用されます。 OSS と Aja x テクノロジーの両方を搭載した Web サイトでは、OSS との直接通信には CORS の使用を推奨します。

CORS に対する OSS のサポート

OSS は、必要に応じて、対応するクロスオリジンリクエストを許可または拒否するため、CORS ルールの設定をサポートしています。 CORS ルールはバケットレベルで設定されます。 詳しくは、「PutBucketCORS」 をご参照ください。

CORS リクエストが許可されているかどうかは、OSS ID 検証とは無関係です。 つまり、OSS CORS ルールは、関連する CORS ヘッダーをアタッチするかどうかを決定するためだけに使用されます。 リクエストがブロックされるかどうかは、ブラウザーによってのみ決定されます。

クロスオリジンリクエストを使用するときは、ブラウザーキャッシュが有効になっているかどうか注意してください。 たとえば、同じブラウザー内の 2 つの Web ページ(www.a.com と www.b.com から発信) より、同じクロスオリジンリソースがそれぞれ同時にリクエストされます。 www.a.com のリクエストが最初にサーバーによって受信された場合、サーバーは Access-Control-Allow-Origin ヘッダー "www.a.com" の情報を持つリソースを返します。 www.b.com がリクエストを開始すると、ブラウザーは以前にキャッシュしたリクエストを返します。 ヘッダーの内容が CORS リクエストと一致しないため、後に続くリクエストは失敗します。

説明 現在、すべての OSS オブジェクト関連のインターフェイスは CORS 検証を提供しています。 また、マルチパートインターフェイスは CORS 検証を完全にサポートしています。

クロスオリジン GET リクエストの例

この例では、Ajax を使用して OSS からデータを取得します。記述を簡単にするため、使用されるバケットの権限はすべて "public" としています。 権限が "private" のバケットにアクセスするための CORS 設定方法も同一で、リクエストに署名をアタッチするだけです。

はじめに

バケットの作成 たとえば、アクセス権を "public-read" に設定してバケット oss-cors-test を作成します。 次に、test.txt という名前のテキストファイルを作成し、それをバケットにアップロードします。

test.txt のアクセスアドレスを取得するには、こちらをクリックしてください。

説明 次のアドレスをテスト用のアドレスに置き換えます。
curl を使用してファイルに直接アクセスします。
curl http://oss-cors-test.oss-cn-hangzhou.aliyuncs.com/test.txt
just for test

ファイルに正しくアクセスできます。

次のコードは、Ajax を使用し、この Web サイトに直接アクセスする方法を説明しています。 Web サイトに直接アクセスするための最もシンプルな HTML コードです。 次のコードをコピーしてローカルの HTML ファイルとして保存し、ブラウザーから開くことができます。 カスタムヘッダーが含まれていないため、このリクエストには事前チェックは必要ありません。

<! DOCTYPE html> 
<html>
<head>
<script type="text/javascript" src="./functions.js"></script>
</head>
<body>
<script type="text/javascript">
// Create the XHR object.
function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {
    // XHR for Chrome/Firefox/Opera/Safari.
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest ! = "undefined") {
    // XDomainRequest for IE.
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    // CORS not supported.
    xhr = null;
  }
  return xhr;
}
// Make the actual CORS request.
function makeCorsRequest() {
  // All HTML5 Rocks properties support CORS.
  var url = 'http://oss-cors-test.oss-cn-hangzhou.aliyuncs.com/test.txt';
  var xhr = createCORSRequest('GET', url);
  if (! xhr) {
    alert('CORS not supported');
    return;
  }
  // Response handlers.
  xhr.onload = function() {
    var text = xhr.responseText;
    var title = text;
    alert('Response from CORS request to ' + url + ': ' + title);
  };
  xhr.onerror = function() {
    alert('Woops, there was an error making the request.');
  };
  xhr.send();
}
</script>
<p align="center" style="font-size: 20px;">
<a href="#" onclick="makeCorsRequest(); return false;">Run Sample</a>
</p>
</body>
</html>

ファイルを開いたら、リンクをクリックします (この例では Chrome が使用されています)。 リンクにアクセスできないことを確認します。

Chrome の開発者ツールを使用してエラーの原因を特定します。

このエラーは、Access-Control-Allow-Origin ヘッダーが見つからないことが原因です。 これは、サーバーが CORS を使用して構成されていないためです。

ブラウザーがオリジンヘッダーを含むリクエストを送信していることを確認するには、ヘッダーインターフェイスに戻ります。 したがって、リクエストはクロスオリジンリクエストです。 Chrome では、ファイルはローカルファイルであるため、オリジンは "null" です。

問題が見つかったら、バケットの CORS 設定を調整して、前の操作の試行が確実に実行されるようにします。 理解を容易にするために、コンソールで CORS 設定を構成する方法について説明します。 CORS 設定が複雑でない場合は、コンソールで CORS を設定することを推奨しています。

CORS 設定は個々の規則で構成されています。 システムは一致する規則を検索する際、各規則は、まず最初の規則の一致がチェックされます。 最初に一致した規則が適用されます。 以下は、最もゆるい設定でルールを追加する方法を示しています。

これは、アクセスがすべてのオリジン、すべてのリクエストタイプ、およびすべてのヘッダーに対して許可されており、最大キャッシュ時間が 1 秒であることを示しています。

設定が完了したら、テストを再度実行します。 結果は次のとおりです。

アクセスリクエストを適切に送信できます。

クロスオリジンアクセスの問題をトラブルシューティングする必要がある場合は、前の図に示すように CORS を設定します。 この設定はすべてのクロスオリジンリクエストを許可します。 この設定でエラーが発生した場合、そのエラーは CORS に関連したエラーではありません。

最もゆるい構成に加えて、より洗練された制御メカニズムを対象の制御用に設定できます。 以下は、規則の一致に対して最も厳しい設定を示しています。

一般的には、最小限の設定で最大限のセキュリティを保証させるため、ユーザーの使用シナリオに適した最も厳しい設定を使用することを推奨します。

POST アップロードにクロスオリジンリクエストを使用する

以下は、署名付きの POST リクエストが使用され、ブラウザーが事前確認リクエストを送信する必要がある、より複雑な例を示しています。

PostObjectSample
説明 上記のコードをダウンロードしたら、以下のすべてのセクションを要件に合わせて変更します。 その後、ユーザーのサーバーで実行させます。

以下ではテストのため、バケットの oss-cors-test の使い方を説明します。テストする前にすべての CORS 規則を削除し、設定を初期状態に戻します。

こちらの Web ページにアクセスし、アップロードするファイルを選択します。

開発者ツールを起動すると、次のコンテンツを閲覧できます。 前述の GET の例に基づくと、簡単に同じクロスオリジンエラーを見つけることができます。 GET リクエストとは異なり、このリクエストには事前チェックが必要です。 次の図に示すように、OPTIONS 応答には CORS ヘッダーがないため、操作は失敗します。

失敗に応じて CORS 設定を変更します。

結果を成功させるため、もう一度操作を実行します。 コンソールに新しくアップロードされたファイルが表示されます。

テスト内容:

$curl http://oss-cors-test.oss-cn-hangzhou.aliyuncs.com/events/1447312129218-test1.txt
post object test
CORS 設定に関する注意事項

CORS 設定項目は次のとおりです。

  • Source: 設定中に完全なドメイン情報を提供します。例えば、前の図に示されているように、http://10.101.172.96:8001 などです。

    例えば http など、プロトコル名を省略しないようにしてください。 既定のポート番号から変更がある場合は、ポート番号を含めます。 よくわからない場合は、ブラウザーのデバッグ機能を使用し、オリジンヘッダーを表示します。 このフィールドはワイルドカード * をサポートしていますが、そのようなシンボルが使えるのは 1 つのみです。 必要に応じて設定を実行します。

  • Method: 要件に基づき、許可されている方法を選択します。
  • Allow Header: 許可ヘッダーのリストを示します。 ヘッダーの省略を避けるために、特に他に指定しない限り、このフィールドを "*" に設定することを推奨します。 ヘッダーは大文字と小文字を区別しません。
  • Expose Header: ブラウザーに対して公開されるヘッダーのリストを示します。 ワイルドカードは使用できません。用途に応じた具体的な設定を選択する必要があります。 ETag ヘッダーなど、必要なヘッダーのみを公開します。 この情報を公開する必要がない場合は、このフィールドを空白のままにします。 ヘッダーは個別に指定できます。 このフィールドでは大文字と小文字は区別されません。
  • Cache Time: 通常、比較的大きな値 (60 秒など) を設定します。

CORS 設定方法は、サービスにアクセスする可能性がある各オリジンに対して個別の規則を設定します。 極力、1 つの規則に複数のオリジンを含めないようにします。また、複数の規則間での重複や競合を避けてください。 その他の権限については、必要な権限をただ付与するだけとなります。

トラブルシューティングのアドバイス

似たようなプログラムがデバッグされる際、他のエラーと CORS エラーは混同されてしまいがちです。

例えば、不正な署名が原因でアクセスリクエストが拒否された場合、アクセス許可の検証が CORS の検証よりも先に行われるため、返される結果に CORS ヘッダー の情報が含まれない可能性があります。 この場合、サーバー上の実際の CORS 設定は正しいにもかかわらず、一部のブラウザーでは直接 CORS エラーを報告してしまいます。 上記の問題に対処するには、次の 2 つの方法があります。

  • HTTP リクエストの戻り値を表示します。 CORS の検証はコアプロセスに影響を与えない独立したプロセスであるため、403 などの戻り値が CORS によって生成されることはありません。 まず、プログラム関連の原因を除外する必要があります。 事前確認リクエストが以前に送信されている場合は、事前確認リクエストの結果を表示します。 正しい CORS ヘッダーが返されると、実際のリクエストはサーバーによって許可されます。 そのため、エラーは他のコンポーネントによって引き起こされている可能性があります。

  • サーバーの CORS の設定を、前の例に示した最もゆるい設定にします。 すべてのオリジンとリクエストタイプを許可するには、ワイルドカードを使用します。 そして、設定を再確認します。それでも検証に失敗する場合は、他の種類のエラーが発生している可能性があります。