S3 の CORS エラーを解決する方法 ── 別ドメインの JavaScript から読めるようにする
記事の「実践」を 1 項目ずつ進めるためのページです。AWS マネジメントコンソールで操作したら、右の一覧にチェックを入れてください。チェックはこのブラウザに保存されます。
前提条件
- リージョン:
ap-northeast-1(東京) - S3・CloudFront の操作権限を持つ IAM ユーザーまたはロールでコンソールにログイン済みであること
- ブラウザは Google Chrome など、開発者ツールを開けるものを使います
以下のリソースが作成済みであることを前提とします。どちらのバケットもパブリックアクセスをすべてブロックしています。
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| S3 バケット(データ用) | cors-lab-data-<アカウントID> | data.json を置いたバケット。CORS 設定なし | Amazon S3 でバケットを作成しオブジェクトを管理する |
| S3 バケット(ページ用) | cors-lab-page-<アカウントID> | index.html(署名付き URL を貼り付けて fetch で読むページ)を置いたバケット | 同上 |
| CloudFront ディストリビューション | (コメント cors-lab page) | ページ用バケットをオリジンアクセスコントロール cors-lab-oac 経由で配信。デフォルトルートオブジェクトは index.html | ― |
index.html は、ページ自身のオリジンを表示し、入力欄に貼り付けた URL を fetch で読みに行って、結果(成功ならレスポンスの本文、失敗ならエラー)を表示するページです。
手順 1: ページを開いてオリジンを確かめる
AWS マネジメントコンソールにログインし、上部の検索バーに CloudFront と入力して、「CloudFront」を選択します。ディストリビューションの一覧で、説明が cors-lab page のディストリビューションの「ドメイン名」をコピーします。
ブラウザの新しいタブで https://<コピーしたドメイン名>/ を開きます。「このページのオリジン」に https://dxxxxxxxxxxxxx.cloudfront.net の形のオリジンが表示されます。この値は手順 4 で使うので控えておきます。
手順 2: data.json の署名付き URL を作る
コンソールに戻り、上部の検索バーに S3 と入力して、「S3」を選択します。左側ナビゲーションの「汎用バケット」から cors-lab-data-<アカウントID> を開き、data.json のチェックボックスを選択します。
「アクション」→「署名付き URL で共有」を選択します。有効期限で「時間」を選び(デフォルトは「分」)、「時間数」に 1 を入力して、「署名付き URL を作成」をクリックします。URL は画面には表示されず、クリップボードにコピーされます。
手順 3: CORS 設定なしで読みに行く
確認ページのタブに戻り、入力欄に署名付き URL を貼り付けて「読み込む」をクリックします。結果欄に「失敗: Failed to fetch」と、ブラウザがレスポンスの読み取りをブロックしたことを示す説明が表示されます。
ブラウザの開発者ツール(Chrome では F12 キー)を開き、「Console」タブを確認すると、No 'Access-Control-Allow-Origin' header is present on the requested resource のような CORS エラーが表示されています。
同じ署名付き URL を、ブラウザのアドレスバーに直接貼り付けて開くと、data.json の中身が表示されます。URL も権限も正しく、S3 はデータを返しています。止めているのはブラウザだと分かります。
手順 4: データ用バケットに CORS 設定を入れる
S3 コンソールで cors-lab-data-<アカウントID> を開き、「アクセス許可」タブを選択します。「Cross-Origin Resource Sharing (CORS)」セクションの「編集」をクリックし、以下の JSON を入力します。AllowedOrigins には手順 1 で控えたオリジンを入れます(末尾に / を付けません)。
[
{
"AllowedHeaders": [],
"AllowedMethods": ["GET"],
"AllowedOrigins": ["https://dxxxxxxxxxxxxx.cloudfront.net"],
"ExposeHeaders": [],
"MaxAgeSeconds": 300
}
]
「変更の保存」をクリックします。「アクセス許可」タブの「Cross-Origin Resource Sharing (CORS)」セクションに、入力した JSON が表示されることを確認します。
手順 5: もう一度読みに行く
確認ページのタブに戻り、同じ署名付き URL のまま「読み込む」をクリックします。結果欄に「成功: HTTP 200」と data.json の中身が表示されます。
開発者ツールの「Network」タブで data.json のリクエストを選択すると、レスポンスヘッダーに Access-Control-Allow-Origin: https://dxxxxxxxxxxxxx.cloudfront.net が付いていることを確認できます。リクエストヘッダーの Origin と一致したルールに従って、S3 がこのヘッダーを返しています。
試しに、CORS 設定の AllowedOrigins を https://example.com に書き換えて保存し、もう一度「読み込む」をクリックすると、手順 3 と同じように失敗します。Origin が一致するルールが無くなったためです。確認したら、手順 4 の値に戻しておきます。