はじめに
目的
本記事は、CDN(コンテンツデリバリネットワーク)を使う際に生じやすいCORS(クロスオリジンリソース共有)の問題をわかりやすく解説することを目的としています。設定ミスで画像やフォントが表示されない、APIが動作しないなどのトラブルを減らし、安全かつ高速に配信するためのポイントを示します。
誰に向けた記事か
・ウェブサイトやウェブアプリを運営している方
・CDN導入を検討中の開発者や運用担当者
・CORSの基本を知りたい初心者
専門用語は必要最低限にし、実例を交えて解説しますので初めての方でも読みやすい構成にしています。
この記事の構成と読み方
本記事は全7章で構成します。まず基本概念を押さえ、次にCDNでの具体的な設定方法、よくあるエラーとその対処法、ベストプラクティス、最後に実装例を示します。現場で試す順序に沿っているため、設定→検証→運用の流れで読み進めると実務に役立ちます。
使い方のヒント(例)
たとえば、別ドメインで配信する画像をほかのウェブページで使うとき、CORS設定がないとブラウザが読み込みを拒否します。こうした具体例を挙げながら、設定手順と確認方法を丁寧に示します。
CDNとCORSの基本概念
CDNとは
CDN(Content Delivery Network)は、世界中の複数サーバーにウェブ資産を置き、利用者に近いサーバーから配信する仕組みです。画像やJavaScript、フォントなどを高速に届け、オリジンサーバーの負荷を下げます。例えば、example.comの画像をcdn.example.netから配ると、読み込みが速くなります。
CORSとは
CORS(Cross-Origin Resource Sharing)は、ブラウザが異なるオリジン間で安全にデータをやり取りするためのルールです。オリジンとは「スキーム+ホスト+ポート」の組み合わせです。ブラウザは同一オリジンポリシーで制約しますが、サーバーが特定のレスポンスヘッダー(例:Access-Control-Allow-Origin)を付けると、許可された場合にのみリソースを利用できます。
仕組みのポイント(簡潔に)
- 単純リクエスト:画像やGETのシンプルな取得では、追加の確認なくレスポンスヘッダーを見て許可を判断します。
- プリフライト:カスタムヘッダーやPUT/DELETEなどを使う場合、ブラウザが先にOPTIONSを送り、サーバーが許可を返す必要があります。
- 認証情報:Cookieや認証ヘッダーを含める際は、Access-Control-Allow-Credentialsが必要で、ワイルドカード(*)は使えません。
CDN利用時の注意点(次章の橋渡し)
CDNは別オリジンになることが多く、CORS設定がないとAPI呼び出しやフォント表示で問題が起きます。次章で具体的な設定方法を見ていきます。
CDN利用時のCORS設定方法
基本方針
CDNを使うときは、CORS設定は原則としてオリジン側で行います。オリジンがレスポンスヘッダー(例:Access-Control-Allow-Origin)を返すことで、ブラウザーがアクセス可否を判断します。CDN側ではそのヘッダーを正しくフォワードし、必要に応じてキャッシュの振る舞いを制御します。
オリジンでのCORS設定(例:Amazon S3)
Amazon S3を使う場合、バケットのCORS設定を追加します。典型的な設定は次のようになります(例):
< CORSRule >
< AllowedOrigin >https://example.com< /AllowedOrigin >
< AllowedMethod >GET< /AllowedMethod >
< AllowedHeader >*< /AllowedHeader >
< /CORSRule >
ワイルドカード(*)は便利ですが、クレデンシャルを使う場合は特定ドメインを指定してください。
CloudFrontのキャッシュ・オリジンリクエストポリシー
CloudFrontでは「オリジンへ転送するヘッダー」にOriginを含めます。レスポンスがOriginごとに変わるなら、キャッシュキーにOriginを含めるか、Originに応じてキャッシュを分けてください。OPTIONS(プリフライト)を許可し、短めのTTLで管理すると安全です。
CloudFront Functionでのヘッダー付与
CloudFront FunctionでViewer RequestにOriginヘッダーを強制追加したり、Viewer ResponseでCORSヘッダーを上書きすることができます。たとえば、Originが無いリクエストに対して固定のOriginを付与する簡単な処理が有効です。
確認とデバッグ手順
- curl -IでAccess-Control-Allow-*ヘッダーを確認します。
- ブラウザーのDevToolsでプリフライト(OPTIONS)の結果を確認します。
- CloudFrontのキャッシュヒット/ミスやS3のログでリクエストの流れを追ってください。
CDN経由でCORSエラーが発生する主な原因と対処法
原因1:レスポンスにCORSヘッダーがない(フォント・画像が表示されない)
CDNやオリジンがAccess-Control-Allow-Originを返していないと、ブラウザが読み込みを拒否します。対処法は次の通りです。
– サーバー/CDNでAccess-Control-Allow-Originを設定する(例: * または特定ドメイン)
– HTMLの該当タグにcrossorigin属性を付ける(フォントや画像で必要)
– ブラウザの開発ツールでレスポンスヘッダーを確認する
原因2:CDNやオリジンの設定不整合(Consoleにエラーが出る)
CDN側とオリジン側でCORS設定が食い違うとエラーになります。対処法:
– CDNの設定画面でCORS許可を有効にする
– オリジンで必要なヘッダーを返すようにする
– 設定変更後にCDNキャッシュをクリアして再確認する
原因3:一部ブラウザだけ失敗する
ブラウザ実装差や拡張機能が原因です。確認方法:
– 別ブラウザやシークレットモードで試す
– 広告ブロッカーやプロキシを一時オフにする
原因4:CDNキャッシュでCORSヘッダーが欠落
CDNが古い応答を返してヘッダーが消える場合があります。対処法:
– キャッシュポリシーを見直してヘッダーを含める
– プリフライト(OPTIONS)要求の扱いを設定する
原因5:企業プロキシやセキュリティ製品の干渉
ネットワーク機器がヘッダーを削ることがあります。IT部門やユーザーに確認し、代理での検証を依頼してください。
トラブル時は、最初に開発ツールでレスポンスヘッダーとステータスを確認し、次にCDNキャッシュをクリアして再試行することをおすすめします。
CDNとCORSのベストプラクティス
オリジンでCORSを一元管理する
CORS設定は可能な限りオリジンサーバーで行ってください。CDNは配信の高速化と可用性を担う役割に集中させ、ポリシーはオリジンで定義します。これにより、複数のCDNを使う場合でも挙動を一貫させやすくなります。
CDN設定:CORS関連ヘッダーを必ずフォワードする
CDNがAccess-Control-Allow-*やVary: Originなどのヘッダーを削除しないように設定します。CDNのキャッシュ設定でこれらのレスポンスヘッダーを保持・転送することが重要です。
プリフライト(OPTIONS)とキャッシュ
OPTIONSレスポンスは適切に返し、Access-Control-Allow-Methods / Allow-Headers / Max-Age を設定してプリフライトをキャッシュします。さらにVary: Originを付けることで、Originごとのキャッシュ整合性を保てます。CDN側でもOriginヘッダーをキーにしたキャッシュ設定を検討してください。
レスポンスとクライアントの整合性
fetchや、、などでリソースを取得する際はcrossorigin属性を付与し、サーバーのAccess-Control-Allow-Credentials設定と整合させます。認証情報を送る場合は具体的なオリジンを返し、ワイルドカード(*)は使わないでください。
セキュリティと公開リソースの取り扱い
公開静的資産(フォントや画像など)は、公開前提ならAccess-Control-Allow-Origin: *でも問題ありません。ただし、認証が絡むAPIや個人情報を扱うリソースは、明示的なオリジン指定と短めのMax-Ageで保護してください。
トラブルシュートの基本ルール
ブラウザの開発者ツール(Network / Console)でレスポンスヘッダーとプリフライトの状態を確認します。リダイレクトやステータスコード(200以外)に注意し、期待するCORSヘッダーが実際に返っているかを確かめてください。
具体的な設定例
1) NGINX(サーバー側)
特定パスに対してヘッダーを追加する例です。例えば /assets 以下の静的ファイルに対してCORSヘッダーを付けます。
location ^~ /assets/ {
root /var/www/html;
add_header "Access-Control-Allow-Origin" "https://example.com" always;
add_header "Access-Control-Allow-Methods" "GET,HEAD" always;
}
Originごとに許可を変える場合はサーバー側でOriginヘッダーをチェックして条件付けします。
2) CloudFront(CDN)の設定
キャッシュポリシーでOriginヘッダーをフォワード(またはオリジンリクエストポリシーに含める)します。これにより、オリジンが受け取ったOriginを基にAccess-Control-Allow-Originを返せます。キャッシュ分割が増える点に注意してください。
3) CloudFront FunctionでOriginを強制付与する例
Originヘッダーがないリクエストに対し固定のOriginを追加する簡単なFunctionです。
function handler(event) {
var request = event.request;
if (!request.headers.origin) {
request.headers['origin'] = { value: 'https://example.com' };
}
return request;
}
4) HTML側の記述例
リソースにcrossorigin属性を付けます。
<link rel="stylesheet" href="/assets/style.css" crossorigin="anonymous">
<script src="/assets/lib.js" crossorigin="anonymous"></script>
5) 注意点
- 認証情報(Cookie等)を使う場合はAccess-Control-Allow-Originにワイルドカード(*)を使わないでください。- Originをフォワードするとキャッシュヒット率が下がることがあります。用途に応じてポリシーを調整してください。
まとめ:CDN×CORSで安全・高速なウェブ配信を実現するために
ここまでのポイントを簡潔にまとめます。CORSはブラウザ側の安全機能であり、CDNを使うときはレスポンスヘッダーの設計が重要です。画像・フォント・JavaScriptが読み込めない場合、まずCORS設定を疑ってください。
- 基本事項
-
サーバー(オリジン)がAccess-Control-Allow-Originなどのヘッダーで許可を出します。CDNはそのヘッダーを転送するか、必要に応じて付与します。ブラウザはヘッダーと要素のcrossorigin属性を照合します。
-
トラブルシュートの手順
- ブラウザのNetworkとConsoleでエラーメッセージを確認します。
- レスポンスヘッダーにAccess-Control-Allow-Originがあるか、値が正しいかを確認します。
- プリフライト(OPTIONS)要求のレスポンスをチェックします。許可されるメソッド・ヘッダーを見ます。
-
CDNがヘッダーを保持しているか、キャッシュ設定で上書きされていないか確認します。
-
ベストプラクティス
- 必要最小限のオリジンだけを許可し、ワイルドカード(*)は慎重に使います。
- 認証情報が必要な場合はcredentialsを有効にし、明示的なオリジン指定を行います。
- CDNでヘッダー転送が難しいときは、エッジ関数でヘッダーを付与します。
最後に、テストを自動化して定期的にチェックすることをおすすめします。CORSとCDNの設定を整えれば、安全で高速な配信が実現できます。