当サイトは、アフィリエイト広告を利用しています
今までの開発でよくCORSがでて、通信ができないことが多々あったが
適当に調べて、対応していた。
どういう仕組みなのかについてちゃんと調べてみたので
忘備録として残しておく。
CORSをまとめるにあたって、まずはCORS界隈の用語を整理しておく
CORSをまず調べて最初にでてくるのが
である。
はい、もうよくわからんってなるのでまずはオリジンから。
オリジンは次の3つの要素から構成される
インターネット上のリソースを特定するための識別子のこと このブログでいうところの"scrawledtechblog.com"
ウェブブラウザーがリソースにアクセスする方法のこと
HTTPとかHTTPSのこと
※FTPやWebSocketなどもある
サーバー上で待ち受ける接続のポイントのこと。
ローカルで開発する時に「localhost:5000」とかでサーバーアクセスするが
この5000部分のこと。
オリジンはドメイン、プロトコル、ポート番号の組み合わせで構成される。
これもよく見る。
同一生成元ポリシー (Same-Origin Policy) はウェブブラウザのセキュリティ機能の一つで
Webページを生成したドメイン以外へのHTTPリクエストができないようになっている。
SPA(Single Page Application)などの場合は、基本的にサーバーが二つある
この場合、WEBサーバーとAPIサーバーは別のオリジンなのでブラウザが
クロスオリジン(異なるオリジン)のリクエストをブロックする。
関連用語が分かったところでCORSについてまとめる。
CORSは正式にはCross-Origin Resource Sharing。オリジン間リソース共有ともいう。
これはウェブページが異なるオリジンからデータを安全に取得できるようにするための仕組み
※具体的にはブラウザに対してクロスオリジンの通信を許可するための仕組み
ブラウザは同一生成元ポリシーによってクロスオリジンの通信を制限するので
クロスオリジンであっても安全に通信できるようにブラウザに指示することをCORSという
ちなみにブラウザを介さずにAPI間で直接通信を行う場合、CORSは関与しないので、CORSによるエラーや制限を心配する必要はない
SPA(Single Page Application)で作られたアプリケーション(クロスオリジンのサーバーがある)を例にして
CORSの仕組みを使って説明してみる。
下記のような異なるオリジンだとする
ユーザーはブラウザでWEBサーバーにアクセスして
WEBページを開く。
そして何らかの操作により、JavaScriptを使用して、異なるオリジンのAPIサーバーに
リクエストが送信される
ブラウザは、このリクエストが同一オリジンポリシーに違反しないかどうかをチェックする
異なるオリジンへのリクエストであるため、ブラウザはCORSプロトコルに従って動作する
クロスオリジン仕様の動きになる
ブラウザは、実際のリクエストを送信する前に「プリフライトリクエスト」をAPIに送信する
これはOPTIONSメソッドを使用したリクエストで、実際のリクエストが安全に送信できるかどうかを確認するために行う。
APIサーバーは、プリフライトリクエストを受け取り、設定されたCORSポリシーに基づいてレスポンスを返す。
このレスポンスには
などが含まれる。
ブラウザは、APIからのレスポンスを受け取り、CORSヘッダーをチェックする
Access-Control-Allow-Origin`ヘッダーにフロントエンドアプリケーションの
オリジン( https://myapp.example.com )が含まれていれば、リクエストは成功となる。
詳しくは後述するが、APIサーバーのCORS設定していた場合、APIサーバー側でクロスオリジンの
許可リストをもっていて、( https://api.example.com )がリストにあれば、Access-Control-Allow-Origin`ヘッダーをつけて返すイメージ。
プリフライトチェックが成功した場合、ブラウザは実際のリクエストをAPIサーバーに送信する。
APIサーバーはリクエストに対するレスポンスをブラウザに送信する。
このレスポンスにもCORSヘッダーが含まれている必要がある。
ブラウザは再度CORSヘッダーをチェックし、問題がなければJavaScriptコードにデータを提供する
ここまでの説明からCORSが発生したということは原因としては
になる。
上記のフローでわかる通り、CORSの設定はAPIサーバー側で設定する必要がある。
APIサーバーは、どのオリジンからのリクエストを許可するかを設定する
これは通許可リスト(whitelist)として管理され、許可リストには、
ブラウザからのリクエストに対してWEBページを作って返している
WEBサーバーのオリジン(例:https://myapp.example.com )を入れるようにする。
クロスオリジンからのリクエストが許可リストにあれば
APIサーバーはレスポンスにAccess-Control-Allow-Originヘッダーを入れてレスポンスするので
通信できるようなる
CORSの設定はAPIサーバー側で設定すると書いたが基本的にはサーバーアプリケーション内で行うことが多い。
だが、場合によってはサーバー自体がCORSを制御することもある。
一般的には、Flask、Django、Express.jsなどのWebフレームワークを使用している場合、
アプリケーションのコード内でCORS設定を行う。
Flaskとかだとそのためのライブラリ(flask-cors)がある。
下記はflaskで全てのオリジンを許可する設定
from flask import Flask, requestfrom flask_cors import CORS# flaskインスタンス作成api = Flask(__name__)# CORS対応CORS(api)
これにより、特定のオリジンからのリクエストを許可できます。
WebサーバーソフトウェアのNginx、Apacheは、サーバー自体でCORS設定を行うことができる。
これは、リバースプロキシやロードバランサーを使用している場合にメリットがある。
サーバー自体でCORSを制御する場合、アプリケーションのコードを変更せずにCORSポリシーを適用できる
CORSについてちゃんと調べてみたら
仕組み自体はそこまで複雑ではなかった。
※実際に対応するとなると別のかもしれないが。
CORSが出る原因と対応方針がわかったので
もうCORSを怖がらずやっていけそう。