クロスサイトリクエストフォージェリ(CSRF)などのセキュリティ攻撃を防止するために、ブラウザは「同一生成元ポリシー(Same-Origin Policy)」という仕組みを実装し、異なるオリジンのリソースへのアクセスに制約をかけています。CORS (Cross-Origin Resource Sharing)は、この制約を一部解除し、異なるオリジン間でリソースを共有するための仕組みです。
例えば、site-a.example.com から他オリジンの site-b.example.com のリソースを参照したい場合、ブラウザは site-b へのリクエストヘッダにアクセス元のオリジン情報を付加します。XMLHttpRequest によるアクセスや、crossorigin="anonymous" を指定した img, script, audio, video, link アクセスの場合などに、Origin: ヘッダが付与されます。
Origin: http://site-a.example.com
これに対し、site-b 側で、site-a へのアクセスを許可する場合、下記の様なレスポンスヘッダを返します。
Access-Control-Allow-Origin: http://site-a.example.com
すべてのオリジンに対してアクセスを許可する場合、ワイルドカード(*) を使用することができます。
Access-Control-Allow-Origin: *
上記のやりとりは「単純リクエスト」と呼ばれるもので、下記の条件が満たされる場合に利用可能なシーケンスです。
上記の条件を満たせない場合は、「プリフライトリクエスト」と呼ばれるもう少し複雑なシーケンスとなります。下記は、条件に含まれてないヘッダ (X-Custom-Header) を送信する例です。まず、Site-A は Site-B に対して、リクエストしたい情報を OPTIONS で事前確認します。
OPTIONS /test HTTP/1.1 Origin: http://site-a.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: X-Custom-Header, Content-Type
これに対し、Site-B は、アクセスを許可する・しないの情報を返します。
Access-Control-Allow-Origin: http://site-a.example.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-Custom-Header, Content-Type Access-Control-Max-Age: 86400
アクセスの許可が得られたのちに、Site-A は実際のリクエストを送信します。
POST /test HTTP/1.1 Content-Type: text/json X-Custom-Header: custom-data
Site-B がこれに応答します。Access-Control-Max-Age で指定した時間が過ぎるまでは、OPTIONS による事前確認なしに POST します。
HTTP/1.1 200 OK
Site-A から Site-B に対して、Site-A の Cookie や HTTP認証による認証情報を渡す場合は、Site-A 側で withCredentials フラグを true にし、Site-B からの OPTIONS 応答で Access-Control-Allow-Credentials フラグで true が返却される必要があります。
<script> window.onload = function() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { console.log("status = " + xhr.status); console.log(xhr.responseText); } } xhr.open("POST", "http://site-b.example.com/"); xhr.withCredentials = true; xhr.setRequestHeader("Content-Type" , "text/json"); xhr.send(JSON.stringify({"sid": getCookie("sid")})); } </script>
Site-A は通常通りの事前確認用の OPTIONS を送信します。
OPTIONS /test HTTP/1.1 Origin: http://site-a.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: X-Custom-Header, Content-Type
Site-B は、Access-Control-Allow-Credentials: true を返却します。
Access-Control-Allow-Origin: http://site-a.example.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-Custom-Header, Content-Type Access-Control-Max-Age: 86400 Access-Control-Allow-Credentials: true
これにより、Site-A は、Cookie などの認証情報を Site-B に POST することが許可されます。