web-dev-qa-db-ja.com

事前に署名されたURLを使用してS3にPUTすると、403エラーが発生します

画像をS3バケットにPUTするために、Nodeを使用してS3のpresignedRULを取得しています。

var aws = require('aws-sdk');
// Request presigned URL from S3
exports.S3presignedURL = function (req, res) {
  var s3 = new aws.S3();
  var params = {
    Bucket: process.env.S3_BUCKET, 
    Key: '123456', //TODO: creat unique S3 key
    //ACL:'public-read',
    ContentType: req.body['Content-Type'], //'image/jpg'
  };
  s3.getSignedUrl('putObject', params, function(err, url) {
      if(err) console.log(err);
      res.json({url: url});
  });
};

これにより、事前に署名されたフォームのURLが正常に取得されます...

https:// [my-bucket-name] .s3.amazonaws.com/1233456?AWSAccessKeyId = [My-ID]&Expires = 1517063526&Signature = 95eA00KkJnJAgxdzNNafGJ6GRLc%3D (期限切れヘッダーを含める必要がありますか? ?)

クライアント側(Webアプリ)に戻ると、angularを使用してHTTPリクエストを生成します。$ httpとngFileUploadの両方を使用しましたが、同様に成功しませんでした。これがngFileUploadコードです。

Upload.upload({
    url: responce.data.url, //S3 upload url including bucket name
    method: 'PUT',
    'Content-Type': file.type, //I have tried putting the ContentTyep header all over
    headers: { 
        //'x-amz-acl':'public-read',
        'Content-Type': file.type, 
    }, 
    data: { 
        file: file,
        headers:{'Content-Type': file.type,}
    },                         
})

ただし、ヘッダーのフォーマット方法に関係なく、常に403エラーが発生するようです。エラーのXMLには、次のように書かれています。

SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.

CORSは問題ではないと思います。もともと私はいくつかのCORSエラーを受け取っていましたが、それらは異なって見え、S3バケットのCORS設定にいくつかの変更を加えることでそれらを取り除くことができました。 presignedURLのリクエストとS3へのPUTリクエストの両方のヘッダーの試行錯誤を何度も試しましたが、適切な組み合わせが見つからないようです。

Console.log 403応答エラーの場合、フィールドに気づきました

config.headers:{Content-Type: undefined, __setXHR_: ƒ, Accept: "application/json, text/plain, */*"}

これは、Content-Typeヘッドが設定されていないということですか?可能な限りどこにでもそのヘッダーを設定した場合、どうすればよいでしょうか。とにかく、少しの間これの壁に頭をぶつけていました...


編集:要求に応じて、私の現在のCORS。 (以前に発生したCORS警告を取り除くためにすべてを投入しました。アップロードが機能するようになった後でのみ、必要なものに絞り込みます。)

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedOrigin>http://localhost:9500</AllowedOrigin>
    <AllowedOrigin>https://localhost:9500</AllowedOrigin>
    <AllowedOrigin>http://www.example.com</AllowedOrigin>
    <AllowedOrigin>https://www.example.com</AllowedOrigin>
    <AllowedOrigin>http://lvh.me:9500</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
    <AllowedHeader>Content-Type</AllowedHeader>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
9
honkskillet

同じ問題に直面しました。事前署名されたURLを作成するために使用したコンテンツタイプが、S3に送信していたオブジェクトのコンテンツタイプと一致していないことがわかりました。事前署名されたURLを作成するときにExpirationヘッダーを追加し(私もそうしました)、S3にプットを行うときにコンテンツタイプが送信されているものをコンソールで正確に確認することをお勧めします。また、データはファイルである必要があり、そこで作成した構造体ではありません。

4
Adheer Araokar