WEBアプリ(以下)を作成した時に、ブラウザのCORSというポリシーによるエラーが発生し、エラー解除に苦戦をしたので、COR2の関連知識についてまとめていきます。
dango-study.hatenablog.jp
目次
CORSのエラーについて
色々調べていくと、以下のように書かれていました。
Cross-Origin Resource Sharing(CORS: オリジン間リソース共有)はサーバーが同一オリジンポリシーを緩和できる標準で、異なるオリジンからのリクエストに対してサーバー側が許可を与えなかった場合に発生するエラーです。・・ちょっとまだ完全に理解ができていないので、用語などを調べながら理解を進めようと思います。
Origin(オリジン)とは
オリジンとは、ウェブコンテンツにアクセスされるために使われるURLの中のスキーム(プロトコル)とホスト(ドメイン)、ポート番号を組みわせたもの
項目 | 詳細 | 備考 |
オリジン | https://www.example.com:8080 | 以下3つを組み合わせたもの |
スキーム(プロトコル) | https:// かhttp:// | 2つの違いは通信が暗号化されているかどうかで、httpsが暗号化されている |
ホスト(ドメイン) | www.example.com等 | いわゆるインターネット上の住所で自身で好きなドメイン名にしたりする |
ポート | 8080等 | ポートに関しては、httpsが443番でhttpが80番が既定番号となり、既定番号ら省略ができるので、ポート番号が付けられないこともある |
同一オリジンポリシーとは
上記の通りプロトコル+ドメイン+ポートが同一の場合は同一オリジンとみなして保護をして、異なるオリジンからのアクセスを制限する仕組みのこと。
主な原則として3つがあります。
- ドキュメントオブジェクトモデル(Document ObjectModel:DOM)は、同じオリジンのスクリプトにしかアクセスできない。
DOMは、HTMLのように文章の構造を示すものやJavaScriptのように操作を示すもの
- XMLHttpRequest(XHR)オブジェクトを使用して、異なるオリジンからデータを取得することはできない。
XHRはサーバーとのデータ通信に使い、ウェブページの更新などを行う目的で使用される
- クッキー(HTTP Cookie)は、同じオリジンのWebページのみに送信されます。
クッキーは、クライアントのWebブラウザとWebサーバとの間で、状態を維持・管理する仕組みで、その通信の際にクライアントのWebブラウザに保存された情報。その後のリクエストとともにサーバーに送信され、ログイン状態の維持などの役割で使用される。
つまり、あるオリジン(Webサーバー)の更新は、同一オリジン(内包したプログラム)やクライアント側でのみ行われ、異なるオリジンからの操作/情報取得等を制限する仕組みと思われます。
CORSの制限対象
同一オリジンポリシーの考え方を踏まえるとCORS(オリジン間リソース共有)の考え方は、なんとなく理解ができ、異なるオリジンからのHTTPリクエストが制限対象となります。
今回のエラーケースでいうと、アーキテクチャが以下の通りで、CORSのエラーが初期段階で出ていました。
恐らく、JavaScriptからXMLHttpRequestでAPI Gatewayからデータを取得しようとしていた為、CORSエラーが発生したと思われます。
(追記)アーキテクチャ
CORSエラーの解決方法
全て網羅できていなさそうですが、対処方法を以下にまとめます。
サーバー側で必要なHTTPレスポンスヘッダーを設定する
この方法が、私がWEBアプリを作成時に対応した方法です。サーバー側で、必要なHTTPレスポンスヘッダーを設定することで、異なるオリジンからのリクエストを許可することができます。具体的には、Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-HeadersなどのHTTPレスポンスヘッダーを設定することが必要です。これらのヘッダーは、CORSエラーを回避するために必要な情報を提供するために使用されます。
詳細は、以下に記載されています。
API Gateway からの CORS エラーのトラブルシューティング | AWS re:Post
まとめ
CORSエラーは、異なるオリジン間での通信が必要な場合に発生する問題です。CORSエラーを回避するためには、サーバー側で必要なHTTPレスポンスヘッダーを設定することや、プロキシを使用することができます。開発をしていて障害になるのは、こういった制限ルールなどが多いので、こういった知識をひとつづつ学んでいかないといけないなと思いました。