クロスオリジンリソース共有(クロスオリジンリソースきょうゆう、略称:CORS、オリジン間リソース共有、英語:Cross-Origin Resource Sharing ) は、ウェブページを配信したドメインとは異なるドメインのサーバー上にある制限されたリソースへのアクセスを、ウェブページに許可するものである。すなわち、同一生成元ポリシーを安全に回避するための仕組みである。
ウェブページは、オリジン間(cross-origin)の画像、スタイルシート、スクリプト、iframe、動画を自由に埋め込むことができる。特定の「クロスドメイン」リクエスト、特にAjaxリクエストは、同一オリジンポリシーによってデフォルトで禁止されている。CORSは、ブラウザとサーバーが対話し、オリジン間リクエストを許可することが安全かどうかを判断する方法を定義するものである。CORSは、純粋な同一オリジンリクエストよりも高い自由度と機能性を可能にするが、すべてのオリジン間リクエストを単純に許可するよりも安全である。
CORSの仕様は、WHATWGのFetch Living Standardの一部として含まれている。この仕様は、CORSが現在ブラウザでどのように実装されているかを記述している。以前の仕様は、W3C勧告として公開されていた。
技術概要
別のドメインを指す<form>タグを使用したり、安全リストにないヘッダーを含んだりすることで作成できないJavaScriptからのHTTPリクエストの場合、仕様はブラウザがリクエストを「プリフライト」することを義務付けている。これは、HTTPのOPTIONSリクエストメソッドを用いてサーバーにサポートされているメソッドを問い合わせ、サーバーからの「承認」を得た上で、実際のHTTPリクエストメソッドで実際のリクエストを送信するものである。サーバーはまた、リクエストと共に「クレデンシャル」(CookieやHTTP認証データを含む)を送信すべきかどうかをクライアントに通知することもできる。
単純リクエストの例 ユーザーがhttp://www.example.comにアクセスし、そのページがhttp://service.example.comからデータを取得するためにオリジン間リクエストを試みるとする。CORS互換のブラウザは、次のようにservice.example.comへのオリジン間リクエストを試みる。
ブラウザは、親ページを配信したドメインを含む追加のOriginHTTPヘッダを付けてGETリクエストをservice.example.comに送信する。<nowiki>Origin: http://www.example.com</nowiki>service.example.comのサーバーは、以下の3つの応答のうちの1つを返す。 リクエストされたデータと、そのオリジンからのリクエストが許可されていることを示すAccess-Control-Allow-Origin (ACAO) ヘッダ。この場合は次のようになるべきである。<nowiki>Access-Control-Allow-Origin: http://www.example.com</nowiki> リクエストされたデータと、すべてのドメインからのリクエストが許可されていることを示すワイルドカード付きのAccess-Control-Allow-Origin (ACAO) ヘッダ。Access-Control-Allow-Origin: * サーバーがオリジン間リクエストを許可しない場合のエラーページ
ワイルドカードの同一オリジンポリシーは、ページまたはAPIの応答が、どのサイトのどのコードからもアクセス可能であることを意図している場合に適切である。Google Fontsのような公開ホスティングサービスで自由に利用できるウェブフォントがその一例である。
"*"という値は、リクエストがクレデンシャルを提供することを許可しないという点で特別である。つまり、クロスドメインリクエストにおいてHTTP認証、クライアントサイドSSL証明書、またはCookieの送信を許可しない。
CORSアーキテクチャでは、Access-Control-Allow-Originヘッダは元のWebアプリケーションサーバー(www.example.com)ではなく、外部のWebサービス(service.example.com)によって設定されることに注意が必要である。ここで、service.example.comはCORSを使用して、ブラウザがwww.example.comからservice.example.comへのリクエストを承認することを許可する。
サイトが "Access-Control-Allow-Credentials:true" ヘッダを指定している場合、第三者のサイトが特権的なアクションを実行し、機密情報を取得できる可能性がある。
プリフライトリクエストの例 特定の種類のクロスドメインAjaxリクエストを実行する際、CORSをサポートするモダンブラウザは、アクションを実行する権限があるかどうかを判断するために、追加の「プリフライト」リクエストを開始する。オリジン間リクエストは、ユーザーデータに影響を与える可能性があるため、このようにプリフライトされる。
OPTIONS / Host: service.example.com Origin: http://www.example.com Access-Control-Request-Method: PUT
service.example.comがアクションを受け入れる意思がある場合、以下のヘッダで応答することがある。
Access-Control-Allow-Origin: http://www.example.com Access-Control-Allow-Methods: PUT
その後、ブラウザは実際のリクエストを行う。service.example.comがこのオリジンからのクロスサイトリクエストを受け入れない場合、OPTIONSリクエストに対してエラーで応答し、ブラウザは実際のリクエストを行わない。
ヘッダ CORSに関連するHTTPヘッダは次のとおりである。
リクエストヘッダ Origin Host Access-Control-Request-Method Access-Control-Request-Headers
レスポンスヘッダ Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Expose-Headers Access-Control-Max-Age Access-Control-Allow-Methods Access-Control-Allow-Headers
ブラウザの対応状況 CORSは、以下のレイアウトエンジンをベースとするすべてのブラウザでサポートされている。 BlinkおよびChromiumベースのブラウザ(Chrome 28+、Opera 15+、Amazon Silk、Android 4.4+ の WebView、Qt の WebEngine) Gecko 1.9.1(Firefox 3.5、SeaMonkey 2.0)以上。 Trident 6.0(Internet Explorer 10)はネイティブでサポート。Trident 4.0 & 5.0(Internet Explorer 8 & 9)は、XDomainRequestオブジェクトを介して部分的にサポート。 Prestoベースのブラウザ(Opera)はOpera 12.00およびOpera Mobile 12以降でCORSを実装しているが、Opera Miniでは実装していない。 WebKit(初期のリビジョンは不明、Safari 4以上、Google Chrome 3以上、おそらくそれ以前)。 Microsoft Edge 全バージョン。
歴史 オリジン間サポートは、当初2004年3月にTellme NetworksのMatt Oshry、Brad Porter、Michael Bodellによって、VoiceXML 2.1に含めるために提案された。これはVoiceXMLブラウザによる安全なオリジン間データリクエストを可能にするためであった。このメカニズムは本質的に一般的であり、VoiceXMLに特有のものではないと見なされ、その後実装ノートとして分離された。W3CのWebAppsワーキンググループは、主要なブラウザベンダーの参加を得て、このノートを正式なW3C勧告に向けたW3C作業草案として形式化し始めた。
2006年5月に最初のW3C作業草案が提出された。2009年3月には草案の名称が「Cross-Origin Resource Sharing」に変更され、2014年1月にはW3C勧告として承認された。
セッション管理との関係 CORSの仕様には、クロスオリジンリクエストにおいてCookieなどの認証情報の送信を許可する Access-Control-Allow-Credentials ヘッダおよび withCredentials 属性が定義されている。これは、初期のWeb APIにおいて、異なるオリジン間でCookieを用いたセッション管理を行うために利用されていた。
しかし、プライバシー保護を目的としたブラウザによるサードパーティCookieの規制や、CSRF(クロスサイトリクエストフォージェリ)対策の観点から、クロスオリジン間でのCookie送信を避ける考えが広まった。その代替として、トークン(JWTなど)をブラウザの localStorage に保持し、CORSを利用して Authorization ヘッダで送信する設計が主流となった。
その後、ブラウザ側に生のトークンを保持することはクロスサイトスクリプティングによるトークン窃取のリスクを高めるという懸念から、フロントエンドの直近に中継サーバーを置く BFF(Backend For Frontend) アーキテクチャが考案されている。BFFとブラウザの間を同一生成元(Same-Origin)にすることで、CORSやサードパーティCookieの制約を受けずに安全な HttpOnly Cookieによるセッション管理が行えるため、セキュリティ要件の高いアプリケーションでは、CORSを利用したトークンベースの認証から、BFFを介した伝統的なCookie認証への回帰が見られる。
CORS と JSONP JSONPの主な利点は、CORSのサポート以前のレガシーブラウザ(Opera MiniおよびInternet Explorer 9以前)で動作する能力にあった。CORSは現在、ほとんどのモダンなウェブブラウザでサポートされており、JSONPパターンの現代的な代替として使用できる。CORSの利点は次のとおりである。
JSONPがGETリクエストメソッドのみをサポートするのに対し、CORSは他のタイプのHTTPリクエストもサポートする。 CORSにより、ウェブプログラマは通常のXMLHttpRequestを使用でき、JSONPよりも優れたエラーハンドリングをサポートする。 JSONPは、外部サイトが侵害された場合にクロスサイトスクリプティング(XSS)の問題を引き起こす可能性があるが、CORSはウェブサイトが手動で応答を解析してセキュリティを向上させることを可能にする。
関連項目 Content Security Policy 同一生成元ポリシー XMLHttpRequest JSONP
脚注
外部リンク Fetch Living Standard (CORSの現行仕様) Setting CORS on Apache with correct response headers allowing everything through 様々な(Web)サーバーでCORSサポートを有効にするための詳細なハウツー情報 HTML5 Rocks がCORSの仕組みを詳しく解説 オンラインCORS設定ミススキャナ