$30 off During Our Annual Pro Sale. View Details »

CORSをちゃんと理解する atmaバックエンド勉強会#4

CORSをちゃんと理解する atmaバックエンド勉強会#4

atmaバックエンド勉強会#4の資料です。

Yamaguchi Takahiro

July 07, 2021
Tweet

More Decks by Yamaguchi Takahiro

Other Decks in Technology

Transcript

  1. CORSをちゃんと理解する
    2021/07/07 #4 atma勉強会 nyk510

    View Slide

  2. 質問です。

    View Slide

  3. CORSって知ってますか?

    View Slide

  4. CORS
    Cross-Origin Resource Sharing
    オリジン間リソース共有

    View Slide

  5. 名前ぐらいは聞いたことある?
    エラーで見たことはある?
    よくわかんない?けどなんかヘッダーに設定
    したら直るやつ?

    View Slide

  6. ちゃんと理解しましょう!

    View Slide

  7. CORSの定義
    追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブ
    アプリケーションに、異なるオリジン にある選択されたリソースへのア
    クセス権を与えるようブラウザーに指示するための仕組みです。

    View Slide

  8. CORSの定義
    追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブ
    アプリケーションに、異なるオリジン にある選択されたリソースへのア
    クセス権を与えるようブラウザーに指示するための仕組みです。

    View Slide

  9. オリジンて何?

    View Slide

  10. オリジン
    URLのプロトコルとホスト(ドメイン)、ポートで識別されるもの
    全部が一緒だと同じオリジンとなる
    例えば https://hoge.com に対して
    ● 同じ: https://hoge.com/foo/bar.html / https://hoge.com:443
    ● 違う: http://hoge.com / https://api.hoge.com

    View Slide

  11. CORSの定義
    追加の HTTP ヘッダーを使用して、
    あるオリジンで動作しているウェブアプリケーション(ex: フロントエンド)に、
    異なるオリジン にある選択されたリソース (ex: バックエンド)への
    アクセス権を与えるようブラウザーに指示するための仕組みです。

    View Slide

  12. CORSの定義からわかること
    ● 特定のオリジンのアプリから、別のオリジンのデータ(リソース)を
    取ってくる権限を定めたものである。
    ● ブラウザーの仕組みである
    ○ 例えば terminal からのアクセスは関係ない

    View Slide

  13. なんでこんなのがあるの?
    ● セキュリティ的観点から同じオリジン以外の情報を取ってこれないようにしてい
    るから
    ● 取ってこようとしている先のオリジンが許可した時だけデータのやり取り(リソー
    ス共有)ができるホワイトリスト方式になっている。
    以下の説明では
    ● ブラウザで表示されているオリジン: Alice
    ● 異なるオリジン: Blob
    として説明します。

    View Slide

  14. ブラウザは、どうやって許可されているかを知るの?
    ● ブラウザは一度普通にBobへとリクエストを送りBobはレスポンスを返す
    ● ブラウザはレスポンス内の Access-Control-Allow-Origin ヘッダーをみる
    ○ リクエスト元の Origin がこの中に入っていれば許可されたとみなす。
    ○ ワイルドカード * 指定も出来る。この場合何でも許可されたとみなす。
    ○ それ以外は許可されていないリクエストとみなす。
    ● 許可されている時
    ○ レスポンスを展開して js からアクセス可能
    ● 許可されていない時
    ○ ブラウザが強制的に処理を止めてエラーになる. js からは「何かしらのエ
    ラーが起こった」しかわからない(これはセキュリティのため)

    View Slide

  15. Bob から見ると…
    ● 自分を呼び出してもオッケーなサイトを Access-Control-Allow-Origin に入れる
    ● するとそれ以外のオリジンでは、ブラウザからBobの情報を参照できない
    ● すくなくともブラウザでアクセスして悪さする外部サイトの脅威を減らせて良い

    View Slide

  16. アクセス許可の方法
    ● 単純リクエスト
    ● プリフライトリクエスト

    View Slide

  17. 単純リクエスト
    ● 相手サーバ Bob に副作用を起こさないようなリクエスト
    ● 先のフローと同様のやり方で許可を判定する
    ● method: GET/HEAD/POST
    ● content-type: application/x-www-formurlencoded, multipart/form-data,
    text/plan

    View Slide

  18. プリフライトリクエスト
    ● 単純リクエストでないものが該当 ・ ex:) POSTで json を送りたい
    フロー
    ● 許可を取るリクエスト (OPTION) を自動的にブラウザが Bob へ送信
    ○ 今からこういうことするのでオッケーですかというお伺い
    ○ これがプリフライトリクエスト
    ● Bobは要求に従って何を許可するかを返信
    ○ ex). POSTはOK / application/json はOK
    ● ブラウザは許可内容をみる (Bobは何がOKって言っている?)
    ○ やりたいリクエストが許可なら、Bobへ本体のリクエストを送信
    ○ 許可されていなければエラーにする(jsからは失敗内容はわからない)

    View Slide

  19. ブラウザからのリクエストとレスポンス
    ● 何故か method が単数形と複数形あるがこれはお伺い建てるのはひとつだけだから
    ● リクエストだけ origin は origin なのは謎
    要求 リクエストヘッダー レスポンスヘッダー
    methodに対する許可 Access-Control-Request-Method Access-Control-Allow-Methods
    ヘッダーに対する許可 Access-Control-Requests-Header Access-Control-Allow-Headers
    オリジンに対する許可 Origin Access-Control-Allow-Origin

    View Slide

  20. 具体例を見ましょう。

    View Slide

  21. 例: ぐるぐる
    フロントエンド: https://guruguru.science
    バックエンド: https://api.guruguru.science
    これらは別 Origin なので Access-Control-Allow-Origin をバックエンド
    側に仕込んでいないとフロントをブラウザで開いた時バックエンドの情
    報は表示できない。

    View Slide

  22. 例: ぐるぐる・単純リクエスト
    https://api.guruguru.science/competitions/17/
    ブラウザからAPIへ送信して
    いるリクエストヘッダー
    APIからブラウザへ返信され
    たレスポンスヘッダー

    View Slide

  23. 例: ぐるぐる・単純リクエスト
    https://api.guruguru.science/competitions/17/
    リクエストの method が GET なので
    単純リクエストとしてブラウザで処理される。

    View Slide

  24. 例: ぐるぐる・単純リクエスト
    https://api.guruguru.science/competitions/17/
    APIが allow-origin に www.guruguru.science を入
    れている → ブラウザで表示OK

    View Slide

  25. 例: ぐるぐる・プリフライトつきリクエスト
    ログインページ: https://api.guruguru.science/auth/login/
    POSTでかつusername/passwordを送信するため単純ではない。
    おさらい
    ● はじめOPTIONによるプリフライトで確認
    ● 確認がとれれば本体のPOSTを送信

    View Slide

  26. 例: ぐるぐる・OPTIONによるプリフライトで確認
    ブラウザはこれから何を送ろうとしているかをOPTION
    をつかってお伺い (プリフライトリクエスト)
    この場合だと
    「MethodはPOST / ヘッダーには content-type / オリ
    ジンは https://www.guruguru.science ですがよろしい
    でしょうか」

    View Slide

  27. 例: ぐるぐる・OPTIONによるプリフライトで確認
    APIはブラウザの各種 requests に対して何を許可
    しているかを返す。
    API「POSTはOK・ヘッダーも content-type は
    オッケーで、オリジンもOKだよ!」

    View Slide

  28. 例: ぐるぐる・確認がとれれば本体のPOSTを送信
    今回の場合別オリジン(API)から許可がもらえたの
    で本体のPOST処理を送信。
    もう許可はもらえているのでこのリクエストに
    Access-Control-Request 系のヘッダーはない。

    View Slide

  29. まとめ
    ● CORSはオリジンの違うサーバにたいしてブラウザからアクセスするときの制御に
    関する仕組みである。
    ● リクエストの種類によってプロトコルが異なる。

    View Slide

  30. 参考資料
    ● https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
    ● 安全なウェブアプリケーションの作りかた・3.3章

    View Slide