ウェブ開発初心者の皆さん、 CORS(クロスオリジンリソースシェアリング) について聞いたことがありますか?ウェブアプリケーションを開発する上で、CORSは避けて通れない重要な概念です。本記事では、サブドメインやワイルドカードの扱い、no-cors
オプションの使い方、そしてCORSに関連する脆弱性について、初心者にもわかりやすく解説します。
CORS(クロスオリジンリソースシェアリング)とは
CORSの基本概念をわかりやすく解説
CORS(Cross-Origin Resource Sharing)とは、異なるオリジン間でのリソース共有を可能にする仕組みです。CORSが生まれた背景には、同一オリジンポリシーというブラウザのセキュリティメカニズムがあります。同一オリジンポリシーは、プロトコル、ドメイン、ポートが一致しないオリジンからのリソースの取得を制限することで、悪意あるスクリプトによる攻撃を防ぐためのものです。しかし、APIサーバーやサードパーティのサービスを利用する場面が増える中で、この制約を安全に緩和する必要が出てきました。そこで登場したのがCORSです。CORSは特定のオリジンからのアクセスを許可することで、安全にリソースを共有する手段を提供します。
同一オリジンポリシーとサブドメインの関係
同一オリジンとは、プロトコル(http, https)、ドメイン名、ポート番号がすべて一致していることを指します。例えば、https://example.com
とhttps://api.example.com
は、サブドメインが異なるため同一オリジンではありません。このため、サブドメイン間でのリソース共有にはCORSの設定が必要になります。
CORSが必要になる場面とその理由
ウェブアプリケーションが以下の場合、CORSの設定が必要です。
- フロントエンドとバックエンドが異なるオリジンに存在する
- 外部APIを利用する
- CDNなど外部のリソースを読み込む
CORSを適切に設定することで、セキュアに異なるオリジンからのリソースを利用できます。例えば、フロントエンドのアプリケーションがバックエンドAPIからデータを取得する際、CORS設定によって不正なリクエストを防ぎ、信頼できるオリジンからのみデータを受け取ることができます。
CORSの仕組みと設定方法
CORSの仕組みを理解するためには、まず基本的なリクエストの流れを把握することが重要です。ブラウザとサーバー間でどのように通信が行われ、どのように許可されるかを知ることで、プリフライトリクエストの重要性も理解しやすくなります。
プリフライトリクエストとは
プリフライトリクエストとは、ブラウザが実際のリクエストを送信する前に、サーバーに対して許可されているメソッドやヘッダーの確認を行うために送信されるリクエストです。これは特に、カスタムヘッダーやPUT/DELETEなどの特定のHTTPメソッドを使用する際に重要です。プリフライトリクエストは、サーバーがリクエストを受け入れるかどうかを判断し、必要な情報を返すための仕組みです。このプロセスを正しく理解し、設定することで、CORSリクエストのセキュリティと機能性を保つことができます。
Access-Control-Allow-Originとワイルドカード(*)の使い方
サーバー側でCORSを設定する際、レスポンスヘッダーにAccess-Control-Allow-Origin
を追加します。このヘッダーには、許可するオリジンを指定します。
Access-Control-Allow-Origin: https://example.com
すべてのオリジンを許可する場合、ワイルドカード(*
)を使用します。
Access-Control-Allow-Origin: *
しかし、ワイルドカードの使用はセキュリティ上のリスクがあるため、注意が必要です。例えば、すべてのオリジンからのアクセスを許可してしまうことで、悪意のある第三者からの不正なリクエストや、重要なデータの漏洩のリスクが増大します。このため、信頼できるオリジンのみを指定することが推奨されます。
no-cors
オプションの役割と使用時の注意点
フェッチAPIやXMLHttpRequest
を使用する際に、no-cors
オプションを指定すると、シンプルなリクエストのみが許可されます。これは、セキュリティを強化するためですが、レスポンスの内容にアクセスできないなどの制約があります。
fetch('https://api.example.com/data', {
mode: 'no-cors'
});
no-cors
を指定すると、エラーは出ませんが、期待したデータを取得できない場合があるので注意が必要です。
サブドメイン間のリソース共有設定
サブドメイン間でリソースを共有する場合、Access-Control-Allow-Origin
ヘッダーに共有を許可するサブドメインを指定します。
Access-Control-Allow-Origin: https://api.example.com
もしくは、オリジンを動的に設定することで、特定のサブドメインからのリクエストを許可できます。
CORSに関する脆弱性とその対策
CORS設定ミスによる脆弱性のリスク
CORSの設定を誤ると、悪意のあるサイトからの不正なリクエストを許可してしまう可能性があります。特に、認証情報や個人情報を扱うサイトでは、CORSの設定を慎重に行う必要があります。
ワイルドカード指定が招くセキュリティ上の問題
Access-Control-Allow-Origin
にワイルドカード(*
)を使用すると、全てのオリジンからのアクセスを許可してしまいます。これは、XSS攻撃やCSRF攻撃のリスクを高めるため、信頼できるオリジンのみを指定することが推奨されます。
安全なサブドメイン間通信のためのベストプラクティス
-
特定のサブドメインのみを許可する
-
認証情報を含むリクエストでは、ワイルドカードを使用しない
-
プリフライトリクエストを適切に処理する
(CORSのリクエストの中には、実際のリクエストを送る前にブラウザがサーバーに確認を行う「プリフライトリクエスト」が含まれます。このリクエストは、特にカスタムヘッダーや認証情報が含まれる場合に重要です。プリフライトリクエストが正しく処理されないと、ブラウザはリソースへのアクセスをブロックしてしまいます。)
これらの対策を講じることで、サブドメイン間での安全なリソース共有が可能になります。
CORSの実践的な設定例とトラブルシューティング
具体的なCORS設定例(サーバー別)
Node.js(Express)での設定例
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: 'https://example.com',
optionsSuccessStatus: 200
}));
Apacheでの設定(.htaccess
)例
Header set Access-Control-Allow-Origin "https://example.com"
エラー | 解決策 |
---|---|
No 'Access-Control-Allow-Origin' header is present on the requested resource. | サーバー側でAccess-Control-Allow-Origin ヘッダーを正しく設定する |
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. | 認証情報を含むリクエストでは、ワイルドカードではなく特定のオリジンを指定する |
開発環境でのCORS設定とデバッグ方法
開発環境では、CORSエラーが発生した場合にブラウザのデベロッパーツールを使用して詳細を確認します。例えば、Google Chromeの場合、F12キーを押すか右クリックして「検証」を選択し、コンソールタブでエラーメッセージを確認します。ネットワークタブではリクエストとレスポンスのヘッダーを詳しく確認できます。また、一時的にCORSを無効化する拡張機能を使用して原因を特定することも有効です。ただし、本番環境では必ず正しいCORS設定を行ってください。
この記事のまとめ
CORSは、ウェブアプリケーション開発において重要な概念であり、正しく理解し適切に設定することで、セキュアかつ機能的なアプリケーションを構築できます。本記事では、初心者の方にもわかりやすくCORSの基本から設定方法、サブドメインやワイルドカードの扱い、脆弱性対策について解説しました。CORSに関する正しい知識を身につけて、安全なウェブ開発を進めていきましょう。
参考資料
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.03.30
フロントエンジニアを目指す初心者向け TypeScriptの基礎を解説
この記事の目的は、初心者にもわかりやすくTypeScriptの基礎から実践的な使い方までを解説し、TypeScriptを使ったコーディングに必要な知識を身につけてもらうことです。
- エンジニア
- フロントエンド
- JavaScript
- TypeScript
2024.08.24
Reactの基本、useContextを理解しよう
今回は、コンポーネント間でデータを共有するのに役立つuseContextについて解説します。
- React
- フロントエンド
2024.09.22
JavaScriptの基礎、Promiseを理解しよう
Promiseの仕組みを理解すると、非同期処理で取得したデータをどう扱えばよいかが見えてきて、スムーズにコードを書けるようになります。基本をしっかり学ぶことで、JavaScript全体の理解が深まり、学習効率も上がるはずです。
- JavaScript
- フロントエンド