预签名的S3 URL签名不匹配

时间:2023-02-11 23:07:05

Title says everything. Here is my code;

标题说明了一切。这是我的代码;

I'm using node-formidable for files.

我正在使用node-formidable文件。

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;

成功上传后,url变量返回s3 url,类似这样;

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

但仍然收到SignatureDoesNotMatch错误。在描述中说

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?

我错过了什么?

2 个解决方案

#1


0  

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

试一试。您需要上传对象,然后针对现有对象生成签名的URL。

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

#2


0  

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

我在使用S3.getSignedUrl('putObject',serverside,然后尝试使用该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.

在我的案例中,我注意到的可能与您的相关的是,使用所有S3.getSignedUrl创建的签名会考虑请求标头。因此,如果您要生成URL,它将失败并显示您收到的相同错误消息,除非使用相同的标头发送。

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.

使用相同的url生成时,以下请求失败。此请求来自浏览器。

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

#1


0  

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

试一试。您需要上传对象,然后针对现有对象生成签名的URL。

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

#2


0  

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

我在使用S3.getSignedUrl('putObject',serverside,然后尝试使用该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.

在我的案例中,我注意到的可能与您的相关的是,使用所有S3.getSignedUrl创建的签名会考虑请求标头。因此,如果您要生成URL,它将失败并显示您收到的相同错误消息,除非使用相同的标头发送。

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.

使用相同的url生成时,以下请求失败。此请求来自浏览器。

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