色々なサイトを歩き回って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とか)に応じてプリフライトリクエストが出る出ないの条件とか、書き足りないけど一旦ここで終わるよ!