クロスオリジンリソース共有とは何ですか?
クロスオリジンリソース共有 (CORS) は、アプリケーションを統合するためのメカニズムです。CORS は、特定のドメインにロードされたクライアントウェブアプリケーションが異なるドメイン内のリソースと通信する方法を定義します。複雑なアプリケーションはクライアント側のコードでサードパーティーの API やリソースを参照することが多いため、CORS が役立ちます。例えば、アプリケーションはブラウザを使用して動画プラットフォーム API から動画をプルしたり、公開フォントライブラリのフォントを使用したり、全国の気象データベースから気象データを表示したりできます。CORS を使用すると、クライアントブラウザは、データ転送の前にリクエストが認可されているかどうかをサードパーティーのサーバーに確認することができます。
クロスオリジンリソース共有が重要なのはなぜですか?
インターネット技術がまだ新しかった時代では、クロスサイトリクエストフォージェリ (CSRF) の問題がありました。これらの問題では、被害者のブラウザから別のアプリケーションに偽のクライアントリクエストが送信されていました。
たとえば、被害者が銀行のアプリケーションにログインしたとします。その後、だまされて新しいブラウザタブに外部ウェブサイトを読み込まされたとします。そして、その外部ウェブサイトは被害者のクッキー認証情報を使用して、被害者になりすましてデータを銀行のアプリケーションに中継するのです。結果として、権限のないユーザーが銀行のアプリケーションに意図せずアクセスするようになったのです。
このような CSRF 問題を防ぐことを目的として、すべてのブラウザが同一オリジンポリシーを実装するようになりました。
同一オリジンポリシー
現在、ブラウザでは、クライアントはクライアントの URL と同じオリジンのリソースにのみリクエストを送信できるようになっています。クライアントの URL のプロトコル、ポート、およびホスト名はすべて、要求するサーバーと一致する必要があります。
たとえば、以下の URL とクライアント URL http://store.aws.com/dir/page.html のオリジンを比較してみましょう。
URL |
成果 |
理由 |
http://store.aws.com/dir2/new.html |
同一オリジン |
パスのみが異なる |
http://store.aws.com/dir/inner/other.html |
同一オリジン |
パスのみが異なる |
https://store.aws.com/page.html |
異なるオリジン |
異なるプロトコル |
http://store.aws.com:81/dir/page.html |
異なるオリジン |
別のポート (http:// はデフォルトではポート 80) |
http://news.aws.com/dir/page.html |
異なるオリジン |
異なるホスト |
そのため、同一オリジンのポリシーは非常に安全ですが、実際のユースケースでは柔軟性がありません。
クロスオリジンリソース共有 (CORS) は同一オリジンポリシーの拡張です。これは、外部の第三者とリソースを正式に共有するために必要です。たとえば、公開または承認されている外部 API からデータを取得する場合は、CORS が必要です。また、権限のある第三者に自分のサーバーリソースへのアクセスを許可したい場合も、CORS が必要とされています。
クロスオリジンリソース共有の仕組み
標準的なインターネット通信では、ブラウザはアプリケーションサーバーに HTTP リクエストを送信し、データを HTTP レスポンスとして受信して表示します。ブラウザ用語では、現在のブラウザの URL は現在のオリジンと呼ばれ、サードパーティの URL はクロスオリジンと呼ばれています。
クロスオリジンリクエストを行うときのリクエスト/レスポンスのプロセスは次のとおりです。
- ブラウザは、現在のオリジンのプロトコル、ホスト、およびポートに関する情報を含むオリジンヘッダーをリクエストに追加します
- サーバーは現在のオリジンヘッダーをチェックし、要求されたデータとアクセス制御許可オリジンのヘッダーで応答します
- ブラウザはアクセス制御要求ヘッダーを見て、返されたデータをクライアントアプリケーションと共有します
あるいは、サーバーがクロスオリジンアクセスを許可したくない場合は、エラーメッセージで応答します。
クロスオリジンリソース共有の例
https://news.example.com というサイトを例に考えてみましょう。このサイトは、partner-api.com の API からリソースへのアクセスを求めています。
https://partner-api.com の開発者は、まず許可されたオリジンのリストに new.example.com を追加して、サーバー上のクロスオリジンリソース共有 (CORS) ヘッダーを設定します。そのためには、以下の行をサーバー設定ファイルに追加します。
Access-Control-Allow-Origin(アクセス-制御-許可-オリジン): https://news.example.com
CORS アクセスが設定されると、news.example.com は partner-api.com にリソースをリクエストできるようになります。すべてのリクエストに対して、partner-api.com は Access-Control-Allow-Credentials(アクセス-制御-許可-認証情報) : "true" で応答します。 これで、ブラウザは通信が承認されたことを認識し、クロスオリジンアクセスを許可します。
複数のオリジンへのアクセスを許可する場合は、カンマで区切られたリストを使用するか、「*」などのワイルドカード文字を使用して、すべてにアクセス権を付与します。
CORS プリフライトリクエストとは何ですか?
HTTP では、リクエストの方法はクライアントがサーバに実行させたいデータ操作です。一般的な HTTP メソッドには、GET、POST、PUT、DELETE などがあります。
通常のクロスオリジンリソース共有 (CORS) のインタラクションでは、ブラウザはリクエストヘッダーとアクセス制御ヘッダーを同時に送信します。通常これらは GET データリクエストであり、リスクは低いと考えられています。
ただし、一部の HTTP リクエストは複雑と見なされ、実際のリクエストを送信する前にサーバーの確認が必要です。事前承認プロセスはプリフライトリクエストと呼ばれます。
複雑なクロスオリジンリクエスト
クロスオリジンリクエストは、以下のいずれかを使用すると複雑になります。
- GET、POST、HEAD 以外のメソッド
- Accept-Language (受諾言語)、Accept(受諾)、Content-Language(コンテンツ言語) 以外のヘッダー
- multipart/form-data(複数パート/フォームデータ)、application/x-www-form-urlencoded(アプリケーション/x-www-フォーム-エンコード済url)、text/plain(テキスト/無地) 以外のコンテンツタイプヘッダー
そのため、たとえば、既存のデータを削除または変更するリクエストは複雑と見なされます。
プリフライトリクエストの仕組み
ブラウザは必要に応じてプリフライトリクエストを作成します。これは次のような OPTIONS リクエストです。
OPTIONS /data HTTP/1.1 オリジン: https://example.com Access-Control-Request-Method(アクセス-制御-リクエスト-メソッド): DELETE |
ブラウザは、実際のリクエストメッセージの前にプリフライトリクエストを送信します。サーバーは、プリフライトリクエストに応答して、サーバーがクライアント URL から受け入れる意思のあるクロスオリジンリクエストに関する情報を提供する必要があります。サーバーの応答ヘッダーには、次のものが含まれている必要があります。
- Access-Control-Allow-Methods(アクセス-制御-許可-メソッド)
- Access-Control-Allow-Headers(アクセス-制御-許可-ヘッダー)
- Access-Control-Allow-Origin(アクセス-制御-許可-オリジン)
サーバーの応答例を以下に示します。
HTTP/1.1 200 OK Access-Control-Allow-Headers(アクセス-制御-許可-ヘッダー): Content-Type(コンテンツ-種類) Access-Control-Allow-Origin(アクセス-制御-許可-オリジン): https://news.example.com Access-Control-Allow-Methods(アクセス-制御-許可-メソッド): GET, DELETE, HEAD, OPTIONS |
プリフライト応答には、追加の Access-Control-Max-Age(アクセス-制御-最大-年齢)ヘッダーが含まれることがあります。このメトリックは、ブラウザがプリフライト結果をブラウザにキャッシュする時間(秒単位)を指定するものです。キャッシュを使用すると、ブラウザはプリフライトリクエスト間で複数の複雑なリクエストを送信できます。max-age(最大-年齢) で指定された時間が経過するまで、別のプリフライトリクエストを送信する必要はありません。
CORS と JSONP にはどのような違いがありますか?
JSON with Padding (JSONP) は、異なるドメインで実行されている Web アプリケーション間の通信を可能にする古典的な手法です。
JSONP では、クライアントページで HTML スクリプトタグを使用します。スクリプトタグは、外部の JavaScript ファイルをロードするか、HTML ページ内に JavaScript コードを直接埋め込みます。スクリプトには同一オリジンポリシーが適用されないため、JavaScript コードを使用してクロスオリジンデータを取得できます。
ただし、データは JSON 形式でなければなりません。また、JSONP は安全なデータを提供するために外部ドメインの信頼性に依存するため、クロスオリジンリソース共有 (CORS) よりも安全性が低くなります。
最近のブラウザにはセキュリティ機能がいくつか追加されているため、JSONP を含む古いコードでは動作しなくなります。CORS は、クロスオリジンアクセス制御の現在のグローバルウェブ標準です。
CORS のベストプラクティスにはどのようなものがありますか?
サーバーでクロスオリジンリソース共有 (CORS) を設定する際には、次の点に注意する必要があります。
適切なアクセスリストの定義
個々のドメインには、カンマで区切られたリストを使用してアクセス権を付与するのが常に最適です。API を公開したい場合以外は、ワイルドカードの使用は避けてください。ワイルドカードと正規表現を使用すると脆弱性が発生する可能性があります。
たとえば、permitted-website.com というサフィックスが付いたすべてのサイトへのアクセスを許可する正規表現を作成するとします。1 つの表現で api.permitted-website.com と news.permitted-website.com へのアクセスを許可することになります。しかし、この場合maliciouspermitted-website.com などのドメインを使用する可能性のある無許可のサイトへのアクセスも誤って許可してしまうことになります。
リストに NULL オリジンを使わないでください
一部のブラウザでは、ファイルリクエストやローカルホストからのリクエストなどの特定のシナリオで、リクエストヘッダーに null という値が送信されます。
しかし、アクセスリストには null 値を含めないでください。また、null ヘッダーを含む不正なリクエストがアクセスされる可能性があるため、セキュリティ上のリスクも生じます。
AWS は CORS 要件をどのようにサポートできますか?
AWS のサービスの多くには、クロスオリジンリソース共有 (CORS) サポートが組み込まれています。そのため、Amazon Web Services (AWS) でホストされている API やリソースへのクロスオリジンアクセスを制御できます。
CORS をサポートする一部の AWS サービスは次のとおりです。
- Amazon Simple Storage Service (Amazon S3 ) は、あらゆるデータストレージのユースケースに対応する費用対効果の高いストレージクラスを備えた、オブジェクトストレージサービスです。Amazon S3 では、S3 データへのアクセスを許可するオリジン、各オリジンでサポートするオペレーション (HTTP メソッド)、およびその他のオペレーション固有の情報を特定するルールを含む CORS 設定ドキュメントを作成できます。設定には最大 100 個のルールを追加できます。
- Amazon API Gateway は、API の作成、配布、保守、監視、保護を、その規模に関わらず簡単に行えるようにする完全マネージド型のサービスです。Amazon API Gateway コンソールで、1 回のクリックで直接 REST API の CORS を有効にすることができます。
今すぐアカウントを作成して、AWS で API の使用を開始しましょう。