【问题标题】:AWS Lambda S3 GET/POST - SignatureDoesNotMatch errorAWS Lambda S3 GET/POST - SignatureDoesNotMatch 错误
【发布时间】:2016-11-02 19:05:51
【问题描述】:

我已经有一个 Lambda node.js 函数启动并运行了大约 6 个月,没有任何问题。该函数只是获取一个对象并将其从一个存储桶复制到另一个存储桶。

今天,我开始得到:

"SignatureDoesNotMatch: 我们计算的请求签名不 匹配您提供的签名。检查您的密钥和签名方法。”

我使用的代码很简单,有什么建议可以解决这个问题吗?

var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});

exports.handler = function(event, context) {

  var to_bucket = 'my_to_bucket/test';
  var from_bucket = event.Records[0].s3.bucket.name;
  var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
  var size = Math.floor(event.Records[0].s3.object.size / 1024);

  s3.getObject({Bucket: from_bucket, Key: key}, function(err, data) {
    if (err) {
      // send a webhook
    } 
    else {
      s3.putObject({Bucket: to_bucket, Key: key, Body: data.Body, ContentType: data.ContentType}, 
      function(err, data) {
        if (err) {
          // send a webhook
        }
        else {
          // send a webhook
        }
      });
    } // end else
  }); // end getobject
};

更新: 我发现如果发送到存储桶,它工作正常。如果我发送到同一存储桶的任何子文件夹,它会失败。我确实发送到一个子文件夹并最初简化了上面的代码,但我已经更新它以在 to_bucket 中显示一个子文件夹。

【问题讨论】:

  • var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); 这一行看起来很可疑。我认为密钥操作可能是个问题。
  • @kixorz 我刚刚更改了它,但它仍然失败并出现同样的错误(并且已经 6 个月了)。感谢您的尝试。
  • 另外,您正在第 2 行访问特定的 apiVersion。我假设每个 AWS API 计算签名的方式不同。尝试通过删除它来使用最新的。此外,如果您将 aws-sdk 与您的代码打包在一起,请尝试更新它。
  • 此错误消息来自他们的 S3 API,因此问题出在客户端计算签名中。
  • @kixorz decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); 在处理 S3 事件时是必需的,因为 S3 提供了用空格作为 + 而不是 %20 的键 URL 转义。 aws-sdk 将尝试为后续请求重新转义它,这肯定会变成废话。我的 S3 Lambda 函数的代码非常相似,所以我怀疑问题出在其他地方。

标签: amazon-s3 aws-lambda


【解决方案1】:

我找到了解决这个问题的方法。在意识到这是由于存储桶内的文件夹,而不仅仅是发送到存储桶根后,我搜索并找到了以下帖子:https://github.com/aws/aws-sdk-go/issues/562

看起来存储桶不应该包含子文件夹,而是键应该包含。为什么这一直有效到现在是一个谜。这是上面的替换代码:

var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});

exports.handler = function(event, context) {

  var to_bucket = 'my_to_bucket';
  var from_bucket = event.Records[0].s3.bucket.name;
  var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
  var size = Math.floor(event.Records[0].s3.object.size / 1024);

  s3.getObject({Bucket: from_bucket, Key: key}, function(err, data) {
    if (err) {
      // send a webhook
    } 
    else {
      key = 'subfolder/' + key;
      s3.putObject({Bucket: to_bucket, Key: key, Body: data.Body, ContentType: data.ContentType}, 
      function(err, data) {
        if (err) {
          // send a webhook
        }
        else {
          // send a webhook
        }
      });
    } // end else
  }); // end getobject
};

【讨论】:

  • 从技术上讲,它不是一个子文件夹,而是一个键。它仅显示为文件夹。他们可能在 URL 中添加/删除了额外内容,这会导致签名不匹配。
  • @Paul 你我的朋友,为我节省了几个小时!这刚刚开始发生在今天。感谢您分享所有已修复的问题!
  • 同上@Paul!奇怪的是,使用存储桶名称中指定的“文件夹”写入存储桶是有效的,但是从存储桶中读取会引发此错误。感谢您节省时间。
猜你喜欢
  • 2012-05-02
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 2011-10-23
  • 2019-04-29
  • 1970-01-01
  • 2013-10-01
  • 2021-12-04
相关资源
最近更新 更多