会話形式でCORS(オリジン間リソース共有)を理解する

色々なサイトを歩き回ってCORSを「完全に理解した」のでアウトプットしてみます。ここではフロントエンドとバックエンドが別サーバーになっているSPA(シングルページアプリケーション)を想定して解説します。

CORSについてある程度調べた事あるけどいまいちよく分かんないなぁというくらいの方を想定しています。また、正確性は後回しにして、何となく分かる事を優先して説明しています。

登場人物

解説するのに次のロールが登場します。

ブラウザさん
ブラウザさん

ChromeとかFirefoxとかのブラウザだよ!

フロントさん
フロントさん

htmlやJavaScriptを返すウェブサーバーだよ!

バックさん
バックさん

JSONとかを返すAPIサーバーだよ!

悪のサイトさん
悪のサイトさん

悪意のあるサーバーだよ!

人間さん
人間さん

ブラウザを操作する人間だよ!

なにか更新したい時の流れ

なにかデータを更新したい場合の流れは以下の様になります。

ブラウザさん
ブラウザさん

フロントさん、Webページのコンテンツください!

フロントさん
フロントさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータ更新リクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、データ更新してください!

(XMLHttpRequestやfetchでPUTリクエスト)

バックさん
バックさん

りょ

ブラウザさん
ブラウザさん

更新されたのでヨシ!

人間さん
人間さん

更新されたのでヨシ!

なにも考慮しない場合の実際の流れ

しかし、なにも考慮しないデフォルトの設定だと実際には次の様になります。

ブラウザ
ブラウザ

フロントさん、Webページのコンテンツください!

フロントさん
フロントさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータ更新リクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、データ更新してください!

(XMLHttpRequestやfetchでPUTリクエスト)

バックさん
バックさん

え、マヂ無理。

Access to XMLHttpRequest at 'https://バックさん/' from origin 'https://フロントさん' has been blocked by CORS policy

ブラウザさん
ブラウザさん

無理って言われた。ぴえん🥺

人間さん
人間さん

えぇ、、、

何故か?

それは次の様な事がなされたら困るからです。悪のサイトさんには詐欺メールとか、どっかの掲示板とかでリンクを踏ませて誘導します。

ブラウザ
ブラウザ

悪のサイトさん、Webページのコンテンツください!

悪のサイトさん
悪のサイトさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータをめちゃくちゃに更新するようリクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、データをめちゃくちゃにしてください!

(XMLHttpRequestやfetchでPUTリクエスト)

バックさん
バックさん

りょ

ブラウザさん
ブラウザさん

めちゃくちゃになったのでヨシ!

人間さん
人間さん

ふぁ!?

どうするか?

CORSのルールを策定した人達は考えました。リクエストが元々はどのサイトのファイルからリクエストされたものかブラウザが勝手に教えるようにすればいいんじゃね!?と。その結果次の様な流れになりました。

ブラウザ
ブラウザ

悪のサイトさん、Webページのコンテンツください!

悪のサイトさん
悪のサイトさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータをめちゃくちゃに更新するようリクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、データをめちゃくちゃにしてください!

(XMLHttpRequestやfetchでPUTリクエスト)

ブラウザさん
ブラウザさん

あ、これは悪のサイトさんからの要求だよ!

(Originヘッダーに悪のサイトさんのオリジンをセット)

バックさん
バックさん

え、悪のサイトさんとか知らんし。マヂ無理。

Access to XMLHttpRequest at 'https://バックさん/' from origin 'https://悪のサイトさん' has been blocked by CORS policy

ブラウザさん
ブラウザさん

無理って言われた。ぴえん🥺

人間さん
人間さん

⊂(^ω^)⊃ セフセフ!!

だがしかし!

CORSのルールが出来たのは2005年あたりらしいのですが、それ以前のサーバーは当然CORSに対応しておらずOriginヘッダーが設定されていたとしても無視して処理してしまいます。なのでもう一工夫されています。

ブラウザ
ブラウザ

フロントさん、Webページのコンテンツください!

フロントさん
フロントさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータ更新リクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、更新リクエストしたいんだけどいいかな?

(Preflight request)

ブラウザさん
ブラウザさん

あ、これはフロントさんからの要求だよ!

(Originヘッダーにフロントさんのオリジンをセット)

バックさん
バックさん

う~ん、、、フロントさんならいいよ❤️

(レスポンスヘッダーに「Access-Control-Allow-Origin: http://フロントさん」をセット)

ブラウザさん
ブラウザさん

レスポンスヘッダーに「Access-Control-Allow-Origin: http://フロントさん」って書いてある。

リクエスト投げてもOKなのね!

ブラウザさん
ブラウザさん

バックさん、データ更新してください!

(XMLHttpRequestやfetchでPUTリクエスト)

バックさん
バックさん

りょ

ブラウザさん
ブラウザさん

更新されたのでヨシ!

人間さん
人間さん

更新されたのでヨシ!

CORSに対応していないサーバーだった場合

CORSに対応していないサーバーだった場合は次の様になります。

ブラウザ
ブラウザ

フロントさん、Webページのコンテンツください!

フロントさん
フロントさん

はい、どうぞ(.html、.css、.js等)

ブラウザさん
ブラウザさん

お、バックエンドにデータ更新リクエストしろってJavascriptファイルに書いてある

ブラウザさん
ブラウザさん

バックさん、更新リクエストしたいんだけどいいかな?

(Preflight request)

ブラウザさん
ブラウザさん

あ、これはフロントさんからの要求だよ!

(Originヘッダーにフロントさんのオリジンをセット)

バックさん
バックさん

Originヘッダーとかよく分からんけどヨシ!

(レスポンスヘッダーに「Access-Control-Allow-Origin」が無し)

ブラウザさん
ブラウザさん

あ、こいつヤバイ、処理やめとこ、、、

人間さん
人間さん

(^ω^)・・・

最後に

とても参考になった記事です。こっちを読めば丸わかりです。

参考 CORSの仕様はなぜ複雑なのかzenn.dev

まだメソッドの種類(GETとかPOSTとか)に応じてプリフライトリクエストが出る出ないの条件とか、書き足りないけど一旦ここで終わるよ!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です