Node.jsで発行したS3の署名付きURLへアップロードすると403エラーになる
S3にファイルをアップロードする際に、署名付きURLを利用することにしました。
Node.jsで試したところ苦戦したので、忘れない内に記事にします。
Node.jsで署名付きURLを発行する方法はこちらの記事を参考にしました。
{AWS(CloudFront+S3)+Node.js} 署名付きURLを使用したプライベートコンテンツの配信
ダウンロード用署名付きURLの発行はうまくいった
以下のようなコードでダウンロード用署名付きURLの発行はうまくできました。
import AWS from 'aws-sdk';
// 中略。AWSの認証等
// s3インスタンス作成
const s3 = new AWS.S3();
// ダウンロードURL発行
const downloadUrl = await s3.getSignedUrl('getObject', {
Bucket: 'バケット名',
Key: 'オブジェクト名',
Expires: 60,
});
アップロード用署名付きURLの発行でつまづいた
同じ要領でアップロード用署名付きURLを発行したところ、URLの発行自体はできました。
import AWS from 'aws-sdk';
// 中略。AWSの認証等
// s3インスタンス作成
const s3 = new AWS.S3();
// アップロードURL発行
const uploadUrl = await s3.getSignedUrl('putObject', {
Bucket: 'バケット名',
Key: 'オブジェクト名',
Expires: 60,
});
ただし、発行したURLへファイルのアップロードを試したところ、ステータスコード403のレスポンスが返ってきました。レスポンスボディは以下のような感じでした。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>hoge</AWSAccessKeyId>
<StringToSign>hoge</StringToSign>
<SignatureProvided>hoge</SignatureProvided>
<StringToSignBytes>hoge</StringToSignBytes>
<RequestId>hoge</RequestId>
<HostId>hoge</HostId>
</Error>
メッセージを要約すると、署名方法がおかしいとのことです。
署名バージョン4を利用する
調べたところ、以下のIssueを見つけました。
Node.js pre-signed URL for PUT response is 'signature does not match'
こちらによると、署名バージョン4を指定して、URLを発行する必要があるそうです。
// s3インスタンス作成
const s3 = new AWS.S3({
signatureVersion: 'v4',
});
// アップロードURL発行
const uploadUrl = await s3.getSignedUrl('putObject', {
Bucket: 'バケット名',
Key: 'オブジェクト名',
Expires: 60,
});
試しに上記のコードで発行したURLへファイルをアップロードしてみたところ、今度はちゃんとアップロードすることができました!
さいごに
無事に解決してよかったです。今回は以下の記事を参考にさせていただきました。わかりやすい記事、ありがとうございます。