Pre-Signed S3 URL Signature Does Not Match

霸气de小男生 提交于 2019-12-10 13:37:58

问题


Title says everything. Here is my code;

I'm using node-formidable for files.

form.on("end",function(field, file){
        params.Body = fs.createReadStream(params.filePath)
        delete params.filePath;
        S3.getSignedUrl('putObject',params, function(err, url) {
            if(err){console.log(err);}
            console.log(url);
        });
    })

After successful upload, url variable returns s3 url, something like this;

https://bucket-name.s3.amazonaws.com/746575308_8c081369df.jpg?AWSAccessKeyId=[key]&Expires=[date]&Signature=[signature]&x-amz-acl=public-read

But still getting SignatureDoesNotMatch error. In description says

The request signature we calculated does not match the signature you provided. Check your key and signing method.

Here is my parameters

params = {
    Bucket:"bucketname",
    Key: file.name,
    ACL: 'public-read'
}

What am i missing?


回答1:


I ran into the same problem while using S3.getSignedUrl('putObject', serverside, and then trying to use that url clientside.

What I noticed in my case, which might be relevant to yours, is that signatures created with all the S3.getSignedUrl take into account request headers. So if you are generating a URL, it will fail with the same error message you received unless sent with the same headers.

One example of a failure: Generated like this..

var params = { Bucket: 'YourBucket', Key: 'uniqueFileKey', Expires: 10000 };
s3.getSignedUrl('putObject', params, function (err, url) {
      if(err){
        return cb(err);
      }
      return cb(null, url)
    });

The following request fails when a using that same url generated. This request was made from a browser.

RequestMethod: Put
Headers: {
    Accept:*/*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.9
    Connection:keep-alive
    Content-Length:11768
    Content-Type:application/x-www-form-urlencoded; charset=UTF-8
}

And the difference is that the signature above created doesn't include content-type, where the request does specify a content-type. Params need to match headers, or the error thrown will be signature doesn't match.

Successful example below:

var params = { Bucket: 'YourBucket', Key: 'uniqueFileKey', Expires: 10000, Content-Type: 'application/x-www-form-urlencoded; charset=UTF-8' };
s3.getSignedUrl('putObject', params, function (err, url) {
      if(err){
        return cb(err);
      }
      return cb(null, url)
    });



回答2:


Give this a try. You need to upload the object, then generate the signed url against an existing object.

var s3bucket = 'somebucket';
var s3Key = '/some/key',
var body = fs.createReadStream('/some/local/file.txt');

var params = {
    Bucket: s3bucket,
    Key: s3Key,
    Body: body
};
s3.upload(params, function(err) {
    if (err) {
        cb_1(err);
    } else {
        var params = {
            Bucket: s3bucket,
            Key: s3Key,
            Expires: parseInt(ttl)
        };
        s3.getSignedUrl('getObject', params, function(err, url) {
            if (err) {
                console.log(err);
            } else {
                console.log(err);
            }
        });
    }
});


来源:https://stackoverflow.com/questions/24684959/pre-signed-s3-url-signature-does-not-match

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!