CORSについて自分で色々試していたら、僕が勘違いしていたことがあったのでそれについて書きます。
まぁ先に勘違いを書くと、僕は「JavaScriptでリクエストを行うときは必ずプリフライリクエストが飛ぶ」と思ってました。はい、これは間違いですね。
そもそもCORSって?
CORSについて、ざっくり説明すると別のサイトにリクエストを送るときに送っていいか確認する仕組みです。
あるサイト(サイトX)上で、別のサイトのサーバー(サーバーA)にリクエストを行うとしましょう。
CORSの説明
サイトX「ブラウザ君、サーバーAにリクエストしてよ」
ブラウザ「おk、でもちょっと待ってね」
ブラウザ「サーバーA君、リクエスト送っていい?」 ←この確認をプリフライリクエストっていうよ!
サーバーA「この友達リストに載ってるならいいよ」
ブラウザ「おっ、ちゃんとサーバーAの名前があるな。よっしゃリクエスト送るよ!」
だいたいこんなやり取りがあります。
この事前確認、プリフライリクエストで確認してくれるおかげで、関係ないサイトへ悪意あるリクエストを送ろうとしてもブラウザが事前にストップしてくれます。
ざっくり説明するとこんな感じです。
何を勘違いしてたの?
この確認のためのプリフライリクエストなんですが、必ず行われるわけではありません。
シンプルなリクエストの場合、プリフライリクエストでの確認を行わずにリクエストが行われます。
(シンプルなリクエストは「これやったらシンプルなリクエストじゃないよリスト」があって、そのリストを満たしているリクエストです。例えばヘッダーにAuthorizationを付与するとシンプルではないリクエストになり、プリフライリクエストが行われます。)
で、僕が勘違いしていたのは
JavaScript内でリクエストを送った場合、必ずプリフライリクエストが行われる!!!
(間違える人は僕だけだと思いますが、これは間違い!)
こう思ってました。
実際試してみると
<script>
const fetcher = async() => {
const res = await fetch(`http://localhost:3080`, {
method: "GET",
headers: {
},
})
console.log(res.statusText)
}
</script>
これでリクエスト送ろうとすると、プリフライリクエストをしないでそのままリクエストしちゃうんですよね。
サーバー側でもいきなり、本命のリクエストが飛んできて、「あれ?プリフライリクエストきてなくね?」と???状態でした。
ここで僕は
もしかしてJavaScriptでのリクエストならプリフライリクエストが行われるって勘違いじゃね?
と気づきました。
いやー勘違いしてました。
Chromeのコンソールには
なんて出ててよく読もせずに「CORSのエラー出てるし、プリフライリクエストってサーバー側でキャッチできないのかな?」と思ったりもしました。
実際はプリフライリクエストが送られてないだけでした。
今はシンプルなリクエストでもちゃんと設定しないとエラーになるんですね。知らなかった。
あ、上のエラーが出てる時、ちゃんとサーバー側にはリクエストが届いてます。cookieもちゃんとサーバー側で取得できてる、つまりcookieが送信されてるのでちゃんと気をつけないといけないですね。
まとめ
- 「JavaScriptからリクストなら必ずプリフライリクエストを送る」は勘違い
- シンプルなリクエスト(プリフライリクエストを送らないリクエスト)の要件はちゃんと確認しよう!
以上、僕がCORSについて勘違いしていたことでした。セキュリティに関わることなのでもっとちゃんと確認しておくべきでしたね。反省。
余談
自作サイトではサーバー側でカスタムヘッダーのチェックをしてたので、プリフライリクエストが必ず行われるようになってました。
セーフ!
コメント