Access-Control-Allow-Methods を徹底解説 — CORS の振る舞い・設定・セキュリティ対策

はじめに

ウェブ開発においてクロスオリジン通信は避けて通れません。ブラウザはセキュリティのために同一生成元ポリシーを実装していますが、API とフロントエンドを別ドメインで運用するケースが増え、CORS(Cross-Origin Resource Sharing)が重要になりました。本稿では、CORS におけるレスポンスヘッダの一つである Access-Control-Allow-Methods を中心に、その役割、動作、設定例、運用上の注意点を深掘りして解説します。

Access-Control-Allow-Methods とは何か

Access-Control-Allow-Methods は、サーバがどの HTTP メソッドをクロスオリジン要求で受け入れるかを示すレスポンスヘッダです。主にプレフライトリクエストに対するレスポンスで利用され、値はカンマ区切りのメソッド名リストになります(例: GET, POST, PUT, DELETE)。仕様上、このヘッダはプリフライト応答に含めることが期待されており、ブラウザはこの値を参照して実際のリクエストを送るかどうか判断します。

プレフライトとシンプルリクエストの違い

ブラウザはリクエストが「シンプル」であればプレフライトを行いません。シンプルメソッドは GET, HEAD, POST の三種類で、さらに Content-Type が特定の値に限定されています。それ以外のメソッド(PUT, DELETE, PATCH など)やカスタムヘッダ、特殊な Content-Type を伴う場合はプレフライト(OPTIONS)リクエストが送信されます。プレフライトへの返信で Access-Control-Allow-Methods に許可メソッドを列挙することで、ブラウザは実際のリクエストを許可するか判断します。

仕様上のポイント

  • 目的: プレフライトリクエストへの応答で、許可されるメソッドを示すこと。
  • フォーマット: メソッド名のカンマ区切りリスト。大文字が慣例だがトークンとして扱われる。
  • 適用範囲: 基本的に OPTIONS プレフライト応答で使われる。サーバ側で実際にメソッドを拒否しても、ヘッダに列挙していることがブラウザに許可を与えるわけではない。
  • ワイルドカードは使用不可: Access-Control-Allow-Methods にはアスタリスクのようなワイルドカードは認められていない。明示的なメソッド列挙が必要。

典型的な HTTP シーケンス

以下はプレフライトが発生するケースの典型例です。

  • ブラウザが OPTIONS /api/resource を送信(Origin ヘッダあり)
  • サーバが Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers などを含む 200 OK を返す
  • ブラウザはレスポンスを検証し、許可されていれば実際の PUT/DELETE 等のリクエストを送る

よくある設定例

主要サーバでの設定方法は次の通りです。ここでは簡潔に示します。

  • Apache(mod_headers 使用): Header set Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE'
  • Nginx: add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; ただし OPTIONS に対する応答は location ブロックで処理するのが一般的
  • Express.js: res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
  • Flask: flask-cors などを使えば自動で設定可能

注意点として、サーバ側で Access-Control-Allow-Methods をハードコードするだけでなく、実際にサーバのルーティングや認証ロジックがそのメソッドを受け入れることを保証する必要があります。

セキュリティと運用上の注意

Access-Control-Allow-Methods はブラウザ側に許可を与えるためのものであり、サーバのアクセス制御の代替ではありません。以下の点に注意してください。

  • 不要なメソッドを列挙しない: PUT や DELETE を使わない API に対してこれらを列挙すると、攻撃者に余分な情報を与える可能性がある
  • 認証・認可は常にサーバ側で行う: CORS ヘッダはブラウザのアクセス制限に影響するだけで、curl などの非ブラウザクライアントには影響しない
  • クレデンシャル対応時の制約: Access-Control-Allow-Credentials を true にする場合、Access-Control-Allow-Origin にワイルドカードは使えない。併せてメソッド設定にも注意
  • ログと監査: プレフライトの多発は異常なクライアント挙動や不適切なヘッダ設計を示す可能性があるためログを残す

開発とデバッグのコツ

ブラウザの開発者ツールのネットワークタブで OPTIONS レスポンスとレスポンスヘッダを確認するのが基本です。以下をチェックしてください。

  • Origin ヘッダが正しく送られているか
  • Access-Control-Allow-Methods に実際のメソッドが含まれているか
  • Access-Control-Allow-Headers が必要なカスタムヘッダを列挙しているか
  • Access-Control-Max-Age によってプレフライトのキャッシュが有効になっているか

よくある誤解

  • 誤解: Access-Control-Allow-Methods を設定すればサーバ側のアクセス制御はいらない。真実: 必ずサーバ側で認証と権限チェックを行う必要がある
  • 誤解: ワイルドカードでメソッドを許可できる。真実: ワイルドカードはサポートされない
  • 誤解: このヘッダは全てのレスポンスで必須。真実: 主に OPTIONS プレフライト応答で有効だが、他の応答に含めてもブラウザは無害として扱う

実用的な設計ガイドライン

  • 最小権限の原則に従う: API ごとに必要最小限のメソッドのみを列挙する
  • 環境ごとに Origin を限定する: 本番は限定的なオリジンのみ許可し、開発環境でのみ緩める
  • 動的なメソッド制御: 認可の状態によって Access-Control-Allow-Methods を変える設計は理論上可能だが、複雑になるため慎重に扱う
  • プレフライトの負荷対策: Access-Control-Max-Age を設定してプレフライト頻度を下げる

まとめ

Access-Control-Allow-Methods は CORS の中で非常に重要なヘッダであり、主にプレフライト応答に含めてブラウザに許可されるメソッドを伝えます。しかしこれはあくまでブラウザ側のアクセス制御に関わるヘッダであり、サーバ側での認証・認可や入力検証を置き換えるものではありません。適切な列挙、最小権限の運用、プレフライトのキャッシュ設定などを組み合わせることで、安全で効率的なクロスオリジン通信を実現できます。

参考文献