CSRFとCORSについて
概要
CSRFとかCORSとかについて理解が薄かったのでメモ
もし自分以外の方は、こちらを見ていただいた方がわかりやすいと思います。
CORSとは?
Same Origin Policyというのがある。
これは、異なるOriginのサイトに対して、Post リクエストなどを送信できるが、レスポンスを読み取ることはできない。
CORSは、この異なるOriginのレスポンスを読み取ることができるようにするための手法。これを使わないと、新たにAPIを作っても、他のドメインからアクセスできない。
参考: CORS (Cross-Origin Resource Sharing) ってなに?
注意としては、リクエストを送信しているため、SameOriginPolicy によるエラーが出たとしても、サーバ側で処理は行われる。
また、HTMLフォーム送信からだと、SameOriginPolicy によるエラーは発生しない。(Javascriptによる通信のものが対象)
Railsの場合
gem を導入する。
RailsのAPIモードでいい感じにCORS設定をする - Qiita
CSRFとは?
サイトを跨いだ偽装リクエストを送信する攻撃
いろいろ対策の方法はあるが、tokenを使った方法が一番良さそう。
一般的な対策
- cookieかsessionにtokenを保存する。
- 保存されたtokenを form のhidden tag に置いておく
- formから送られたtokenを検証して、正しいものであれば正しいリクエストとする
Railsの場合
RailsのCSRF保護を詳しく調べてみた(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
- RailsでHTMLをレンダリングする。その際に、HMTL内のmetatagと、session cookieにcsrf-tokenが保存される。
- form_forやform_tag を作って、formを生成すると、自動でcsrf-tokenが配置される。
- そのformからリクエストを送ると、csrf-tokenが検証されて、正しいかを判断する。
Rails + Vueを使う場合
VueからAPIに通信を行う時はformを利用しない。
そのため、axiosを用いて、csrf tokenをheaderに追加する。
上述した通り、Railsのmeta tagには、csrf_token が置かれているので、下記のように取得してリクエストを送ればOK。
document.querySelector('meta[name="csrf-token"]').getAttribute('content')
参考: 【Vue】axiosで、デフォルトでCSRFトークンを設定できるようにする - Qiita
Nuxt(SSR)の場合
- NuxtでSSRする際にcsrf token を発行する
- その発行されたtokenをstoreに保存しておく
- APIを叩く時に、storeに保存したtokenを一緒に付け加えてrequestを送る。
- Expressがtokenの検証を行う
参考: Nuxt.jsでcsrfTokenを埋め込みセキュアな通信を行う - Qiita
その他の対策
もしCookieで認証したあとだけを保護したいのならば、違うドメインからCookieを遅れないようにする方法も良さそう。