CORS
Cross-Origin Resource Sharing
前提として、あるドメインAから、別ドメインBのリソース要求は基本的に拒否される。別ドメインのリソースを使うための手続きとして存在するのがCORSらしい
CORSでエラーになる厳密な理由は、同一生成元ポリシーによるブロック。
セキュリティ上の制約により、jsでCORSエラーをハンドリングすることはできない
同一生成元ポリシーによる制限
異なる生成元のリソースに対して、以下の操作が制限される
スクリプトによる別のoriginであるiframeやwindowに対する操作の制限
iframe.contentWindow, window.parent, window.open, window.opener など
キャンバスのコンテキストに対する getImageData() の呼び出し
これによる違反では、以下のようなメッセージがでる(?)
Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. at Image.<anonymous> (http://localhost:8080/:35:21) <canvas> 要素自身に対する toBlob() の呼び出し
キャンバスに対する toDataURL() の呼び出し
異なる生成元と判断される条件
ホスト(ドメインやIP)、スキーム(プロトコル)、ポート番号のいずれかが異なる場合
同一生成元ポリシーによる制約を回避する手続き
手続きには3パターンの種類がある。
単純リクエスト
プリフライトリクエスト
資格情報を伴うリクエスト
CORSの手続きを踏むことで許可される操作
XMLHttpRequest, Fetch API による取得
ウェブフォント(CSS の @font-face)
WebGL テクスチャ。
drawImage() を使用してキャンバスに描画される画像やビデオフレーム。
画像から生成する CSS シェイプ。
おおよそは、GETによるtextの要求の場合
code:js
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();
リクエスト:Originヘッダーを付与する
レスポンス:Access-Control-Allow-Originヘッダーを付与する
単純リクエスト以外の場合(?)
code:js
const xhr = new XMLHttpRequest();
xhr.setRequestHeader('Ping-Other', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');
CORSの手続き自体は自動で進められる模様。
クライアントとしては出来ることは無くて、サーバー側がプリフライトの手続きを踏めるように作らないといけない?
cookieなどの資格情報を付与してリクエストする
応答にAccess-Control-Allow-OriginとAccess-Control-Allow-Credentialsが必須になる
Access-Control-Allow-Originは*(ワイルドカード)が不可になる
CORS手続きを行う事を期待する条件 HTTPヘッダーにOriginが設定されると、CORS的な応答を期待する(?)
XMLHttpRequest
Fetch API
code:js
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});
<img>タグにcrossoriginプロパティを設定
code:html
ImageオブジェクトのcrossOriginプロパティ設定
code:js
var img = new Image();
img.addEventListener('load', doResp, false);
img.crossOrigin='use-credentials';
img.src = reqUrl;
imgタグ周りにおけるCORS
document.createElement('img').crossOrigin;やnew Image().crossOrigin へプロパティ設定する
anonymousで認証情報(cookieなど)を送らない。use-credentialsで認証情報を送る
CORSの啓蒙サイト?
Fetch Metadata Request Headers
CORSの許可応答を機械的に行えるように、ヒント情報を渡す枠組み(?)
登場人物
アクセス元ドメイン(iframeの親とか)
アクセス先ドメイン
クライアント
注:アクセスしたら全てエラーになるのではない。例えば、<img> とか、 <script url=""> みたいなタグによるGETなんかだと、エラーは発生しない。
おおよそのケースでは、 Access-Control-Allow-Origin: * をレンスポンスヘッダに含めれば良い。
---
メモ
withCredentials = true クッキーを書く
サーバー側におけるCORS許可の実装
---
CORSエラーが発生するのはレスポンス受信後。
イメージ的には、レスポンスを受信した後、レスポンスヘッダを確認して、CORS違反であればレスポンスボディを破棄する。ような動き方をしている。