使用预签名url PUT到S3会出现403错误

时间:2018-01-27 14:37:53

标签: angularjs amazon-s3 http-status-code-403 ng-file-upload pre-signed-url

我使用Node获取S3的presignedRUL,以便将图像输入S3存储桶。

vertex shader

这成功检索了形式为...的预签名网址。

https://[my-bucket-name].s3.amazonaws.com/1233456?AWSAccessKeyId=[My-ID]&Expires=1517063526&Signature=95eA00KkJnJAgxdzNNafGJ6GRLc%3D (我是否必须包含过期标题?)

回到客户端(Web应用程序)我使用angular来生成HTTP请求。我使用了$ http和ngFileUpload,但也没有成功。这是我的ngFileUpload代码。

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});
  });
};

然而,似乎无论我如何格式化我的标题,我总是得到403错误。在它所说的错误的XML中,

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,}
    },                         
})

我不认为CORS是一个问题。最初我得到了一些CORS错误,但它们看起来不一样,我让他们对S3存储桶CORS设置进行了一些更改。我已尝试对presignedURL的请求和S3的PUT请求进行大量试验和错误设置,但我似乎无法找到正确的组合。

我注意到当我在console.log中出现403响应错误时,字段

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

这是说Content-Type头没有设置?当我能在任何地方设置标题时,怎么可能呢?无论如何,我的头撞到了墙上一点......

编辑:根据要求,我的当前CORS。 (我把所有内容全部丢掉,以摆脱我之前的CORS警告。只有在我的上传工作完成后,我才会将其削减到必需品。)

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

2 个答案:

答案 0 :(得分:2)

面对同样的问题。发现我用来创建预签名URL的内容类型与我发送给S3的对象的内容类型不匹配。我建议您在创建预签名的URL时添加Expiration标头(我也是这样做的),并在控制台中准确检查在对S3进行放置时要发送的内容类型。另外,数据只需要是文件,而不是您在其中创建的结构。

答案 1 :(得分:0)

我遇到了签名不匹配的 403 错误,我一生都无法弄清楚原因。阅读其他一些示例,其中一个说它必须在 us-east-1 中运行,因为其他区域不支持它。我在 us-east-2,切换和完全相同的代码工作。

尝试使用 us-east-1