Amazon S3でCORS対策

JavaScriptでAmazon S3の画像を取得して表示したい。

JavaScriptでAmazon S3の画像を取得してみる。

const img = new Image();
img.crossOrigin = "anonymous";
img.addEventListener('load', () => this._setImage(img));
img.src = imgSrc;

すると、以下のエラーが発生した。

Access to image at 'https://xxx.s3.ap-northeast-1.amazonaws.com/' from origin 'https://xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  1. AWS マネジメントコンソールにログインして、「Amazon S3」→「パケット」にアクセスする。
  2. 対象のパケットを開く。
  3. 「アクセス許可」の「Cross-Origin Resource Sharing (CORS)」の「編集」ボタンを押し、以下の設定を入力して、「変更の保存」ボタンを押す。

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ]
    }
]

アクセス元のドメインを制限する場合は、AllowedOriginsにアクセスを許可するドメインを設定する。
例:example.comからのアクセスのみ許可する

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "example.com"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ]
    }
]

以上の設定を行うと、エラーは発生しなくなる。

しかし、それでもたまにエラーが発生した。

調べてみると、Chromeのキャッシュの挙動に問題があるようだ。

S3のPresigned URLを使用しているため、画像のURLの末尾にクエリパラメーターを付与するという案は、使えなかった。
Presigned URLにクエリパラメーターを付与するとエラーになる。

img.src = `${imgSrc}&x=${Date.now()}`;

最終的には、画像のURLを使い回さず、画像を表示するたびに新しいURLを作成するようにして対応した。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください