CORSとは?初心者が押さえておくべき仕組みと設定方法

Web開発

はじめに

CORSとは何か

ウェブアプリケーションを作るとき、 CORS (Cross-Origin Resource Sharing) という言葉を耳にすることがあるのではないでしょうか。 これは異なるオリジン間でのリソース共有を制御する仕組みを指します。 オリジンとは、URLを構成するスキームやホスト名、ポート番号が同じかどうかという概念です。

CORSはサーバーとブラウザが連携して動く仕組みであり、ブラウザ側がある種の安全策として機能します。 もしCORSが正しく設定されていないと、データを取得できないエラーに遭遇することもあります。

用語の簡単なおさらい

ウェブ開発では、ブラウザとサーバーがやり取りを行う際にHTTPヘッダーという情報を使います。 Access-Control-Allow-Origin などのヘッダーは、ブラウザが他のオリジンからリソースにアクセスしてもよいかどうかを判断する手がかりです。 ブラウザはサーバーからのレスポンスにそのヘッダーが含まれているかどうかで、アクセスを許可するかどうかを決めます。 こうした仕組みは、ウェブの安全性を保ちつつ、外部リソースの活用を可能にするものです。

CORSの基本概念

リソース間のやり取り

同じオリジンのウェブページからのリクエストは、多くの場合制限なく通るようになっています。 一方、別のオリジンへアクセスする場合には、ブラウザが特別なチェックを行います。 ここで重要なのが同一オリジンポリシーというセキュリティルールです。

例えば、http://example.com で動いているページが、http://anotherdomain.com にあるAPIを呼び出すケースを想定してみてください。 このとき、サーバー側で適切にCORSが設定されていなければ、ブラウザはセキュリティ上の理由からリクエストを拒否することがあります。

仕組みの流れ

実際には、ブラウザがサーバーへリクエストを送信して、サーバーはレスポンスヘッダーにAccess-Control-Allow-Originなどを含めて返します。 ブラウザはそのヘッダーの内容を見て、要求しているオリジンに対してアクセスを許可してよいかどうかを判断します。 場合によってはプリフライトリクエストという追加の問い合わせをブラウザが行い、サーバーが適切に許可を出しているかを事前に確認します。

ブラウザが行う安全対策

同一オリジンポリシー

ウェブブラウザは、基本的に同一オリジンポリシーと呼ばれる仕組みをベースに動作しています。 これは、オリジンが異なるリソース間でデータを自由にやり取りするのを制限するルールです。 この制限がなければ、悪意あるサイトが個人情報を取得するなどのリスクが高まるため、大切な安全策といえます。

同一オリジンポリシーがあることで、たとえば自分の銀行口座のページが開いているタブと、全く無関係なサイトのタブとの間で勝手にデータが交換される状況を防ぐことができます。 CORSは、このポリシーを柔軟に運用できるようにする仕組みとして位置付けられます。

プリフライトリクエスト

ブラウザは、単純なリクエスト以外を行う場合に事前問い合わせとしてOPTIONSメソッドでサーバーにアクセスします。 これがプリフライトリクエストです。 ここでは、どのHTTPヘッダーやメソッドを使ってよいのか、サーバーが許可しているかどうかを確認します。

このプリフライトリクエストに対して、サーバーが Access-Control-Allow-MethodsAccess-Control-Allow-Headers などのヘッダーを返すと、ブラウザは本番のリクエストを送信します。 そうしたやり取りによって、不要なリスクを回避する仕組みになっています。

実際の使用例

シーン1: フロントエンドが別ドメイン

例えば、フロントエンドをhttp://frontend.example.com でホストし、APIサーバーをhttp://api.example.com に置くとします。 この場合、ドメインが異なるため、ブラウザはCORSチェックを行います。 もしサーバーがAccess-Control-Allow-Origin: http://frontend.example.com を返せば、ブラウザはリクエストを許可します。

ただし設定が間違っていると、ブラウザ側で「No 'Access-Control-Allow-Origin' header is present on the requested resource.」のようなエラーが表示されます。 適切にヘッダーを返すことが肝心です。

シーン2: 外部APIとの連携

外部の天気情報APIやSNSのAPIを呼び出すケースでもCORSが関わることがあります。 例えば、JavaScriptのfetchを使って外部APIへリクエストを送るとき、相手がCORSを許可していなければエラーになるでしょう。 このときは、プロキシサーバーを用意して同じオリジンとして扱う、あるいは相手のAPI側でCORSが許可されているかを確認する必要があります。

サーバー側の設定方法

Expressでの設定例

Node.jsとExpressを使った例を見てみましょう。 以下では、corsというミドルウェアを使うと、CORSの許可設定を手軽に実装できます。

const express = require("express");
const app = express();
const cors = require("cors");

app.use(cors());

app.get("/api/data", (req, res) => {
  res.json({ message: "これはサーバーからのデータです" });
});

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

このコードでは、app.use(cors()) を設定することで、あらゆるオリジンからのアクセスを許可しています。 特定のドメインだけを許可したい場合は、オプションを指定することもできます。

ヘッダーを手動で設定

別の方法として、カスタムでレスポンスヘッダーを設定するアプローチもあります。 ミドルウェアを使わず、以下のようにしてヘッダーを付与する方法です。

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "http://frontend.example.com");
  res.header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
  res.header("Access-Control-Allow-Headers", "Content-Type");
  next();
});

このように手動でヘッダーを加えることで、皆さんのアプリケーションに合わせた詳細な設定を行えます。 ただし、設定項目の書き漏れや誤りがあるとエラーの原因になります。

トラブルシューティング

典型的なエラー

CORSまわりでよく見かけるエラーとして、下記のようなメッセージが挙げられます。 ブラウザの開発者ツールで確認すると、具体的な文言を示してくれることが多いです。

  • No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • The CORS policy does not allow access from this origin.
  • Method PUT is not allowed by Access-Control-Allow-Methods.

エラーが発生したときは、サーバーのレスポンスヘッダーが正しく設定されているかどうかをチェックしてみてください。 また、キャッシュを見ている可能性もあるため、リロードして再確認するのも一つの方法です。

原因と対処

CORSエラーの原因は主にサーバー側のヘッダー設定不備か、あるいはプリフライトリクエストへの応答不足です。 たとえば、Access-Control-Allow-Methods に含まれていないHTTPメソッドを使うとエラーが出ます。 プリフライトリクエストで必要なヘッダーが返ってこない場合も同様です。

もし特定のオリジンだけを許可したいのであれば、Access-Control-Allow-Origin にワイルドカード*を使わず、明示的にドメイン名を入れる必要があります。 これらを意識して設定することで、不要なエラーを回避できます。

セキュリティ上の注意点

Allow-Originの指定

サーバーのレスポンスで**Access-Control-Allow-Origin: *** としてしまうと、あらゆるサイトからアクセスできるようになります。 これは便利ですが、データを保護すべき場合にはリスクが高いと言えます。 特に機密情報を扱うAPIは、許可するオリジンを必要最低限に絞るほうが安全です。

外部からのアクセスを想定しているAPIであっても、予期しない連携が生まれる可能性を考慮することが大切です。 あらかじめ想定オリジンだけを許可しておくと、セキュリティレベルを保ちながら柔軟な連携が可能になります。

認証情報を含む場合

クッキーや認証トークンが必要なリクエストをCORS経由で行う場合は、Access-Control-Allow-Credentials: true を設定する必要があります。 また、クライアント側でもフェッチやXHRを行うときに、fetch("...", { credentials: "include" }) のように明示的に指定することがあります。

クッキーを伴うリクエストを別のオリジンから許可すると、意図しないリスクを招く場合があります。 必ず信頼できるオリジンに限定するようにしましょう。

まとめ

ここまでCORSの概要や仕組み、サーバー設定例について見てきました。 CORSはブラウザの同一オリジンポリシーを拡張するものであり、セキュリティと利便性の両立を図る重要な仕組みです。 設定を誤ると、思わぬエラーやリスクを抱えてしまうこともあるので、基本的な構造を理解しておくと安心ですね。

サーバー側での実装では、皆さんが使っている言語やフレームワークに合わせて設定方法が少し異なることがあります。 とはいえ、原理は同じなので、今回紹介した内容を応用すればほとんどのケースに対応できるでしょう。 ぜひ今後の開発で役立ててみてください。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。