同一オリジンポリシーを理解する。CORSエラーの原因と回避方法!
この記事では、同一オリジンポリシーとCORSについて初心者向けに分かりやすく説明する。
CORSエラーはウェブアプリケーションの制作に携わっている人ならば一度は経験する厄介な存在。
Webアプリの開発を円滑におこなたいのならば、同一オリジンポリシーとCORSを正しく理解して、その回避策を知っていることが重要なポイントだ。
いままで同一オリジンポリシーやCORSについて「なんとなく分かる」で済ませてきた人は、この記事を読んでもう一度正しく理解できるように挑戦してほしい。
同一オリジンポリシーとは?
まずは同一オリジンポリシー(同一生成元ポリシー・同一源泉ポリシーとも呼ばれる。)とは何かについて確認しよう。
同一オリジンポリシーとは、ブラウザ上に表示されているリンクやボタンから、外部のAPIサーバーへのHTTPリクエストを制限するための指針。
インターネットブラウザは同一オリジンポリシーに基づき、HTTPリクエストが許可されているかどうかをAPIサーバーへ確認する仕組みを備えている。
セキュリティのリスク
同一オリジンポリシーは以下のようなネットワーク上の攻撃からユーザーを守る役割を果たしている。
- クロスサイト・スクリプティング(XSS)
ユーザーの個人情報などを盗み取るための手法。悪意のあるサイトへと誘導するスクリプトをウェブサイトに仕掛けることにより行われる。入力フォームの脆弱性を突く形でおこなわれる攻撃。 - クロスサイト・リクエストフォージェリ(CSRF)
メール内やウェブサイト上のURLをクリックさせてユーザーを悪意のあるサイトへと誘導し、ターゲットとなるサイトを攻撃させる手法。攻撃者はセッションの脆弱性を利用する。
オリジンの定義
「オリジン」の定義について確認しよう。
オリジンはドメインなどの用語と似たウェブサイトの識別に使われる概念だが、以下の3つの要素を含めて同一とみなされる。
- ホスト – いわゆるドメインの事を指す。サブドメインは識別されるが、サブディレクトリは識別しない。
- スキーム – httpもしくはhttpsを指す。
- ポート – ポートはURLの後に付加する番号で通信先となるソフトウェアの識別に使う。
異なるオリジンの例
- http://website.com/app1
- https://website.com/app2
- http://www.website.com
- http://app.website.com
- http://website.com:8080
CORSとは?
CORS(クロスオリジンリソース共有)とは、オリジンを跨いだリソースの共有という意味で、同一オリジンポリシーにより制限されている。
制限を破るかたちでのHTTPリクエストはエラーとなる。
以下はCORSエラーの典型的なエラーメッセージだ。
ブラウザに実装されているセキュリティのためのメカニズムであることを理解しよう。
CORSの制限の対象
CORSの制限の対象となるのは以下のような行動だ。
- HTTPリクエスト
異なるオリジン間でのHTTPリクエストは原則的に禁止されている。
許可する場合はサーバ-側のAccess-Control-Allow-Originヘッダにリクエスト元となるURLを記述する。 - iFrameの操作
スクリプトを使った異なるオリジンのiFrameに対するwindowなどの操作は禁止されている。 - Canvasの操作
異なるオリジンから取得した画像をCanvasに描画するとgetImgaeData() などの関数の使用が制限される。
プリフライトリクエスト
ブラウザはHTTPリクエストをおこなう際にAPIに対して、このURLがそのリクエストをおこなう権限を備えているかの事前におこなっている。
この確認のためのリクエストはプリフライトリクエストと呼ばれ、その他のリクエストは単純リクエストなどと呼ばれる。
プリフライトリクエストをコンゾールで確認してみると、GETやPOSTなどのリクエストのタイプの欄に OPTIONSと表示されている。
CORSエラーの原因
まずはCORSエラーの原因を確認していこう。
前章でも説明したようにCORSエラーは許可されていない異なるオリジン間でのリクエストをおこなった際に発生する。
また、SSLサーバ証明書が登録されていないためにCORSエラーが発生することもある。
バックエンドサーバーをローカル環境で起動している場合はクライアントの証明書が登録されているかを確認しよう。
CORSエラーの回避方法
CORSエラーを回避していく方法について確認しよう。
Access-Control-Allow-OriginヘッダにURLを追加する
もしアクセスするAPIサーバーが自社で開発したものであるなら、サーバ-のAccess-Control-Allow-OriginヘッダにURLを追加するのがもっとも良い方法だろう。
もし、バックエンドシステムをローカルで起動しているなら自分でURLを追加しサーバーを再起動させればいいだろう。
ブラウザとAPIの間にミドルウェアを挟む
もしアクセスしたいAPIサーバーが自社のもので無い場合は、ウェブサイトとAPIサーバーの間にミドルウェアを挟むという方法も存在する。
http-proxy-middleware:: npmjs.com/package/http-proxy-middleware
ブラウザでURLを開きリスクを許容する
アクセスしたいAPIサーバーが危険性のあるサイトだとブラウザに認識されているためにCORSエラーが発生することもある。
この場合、目的のAPIサーバーをそのブラウザの別のタブで開き「危険を承知のうえでアクセスする」という旨のボタンをクリックするとリクエストが正常にいくパターンもある。
SSLサーバ証明書を追加する
ウェブアプリケーションをローカル環境で起動している場合は、そのクライアントの証明書が登録されていないためにCORSエラーが発生することもある。
その場合、SSLサーバー証明書(Self-signed certificate)を発行してPCのレジストリに登録する。