【问题标题】:AWS S3 - PUT to URL from getSignedUrl() returns 403 SignatureDoesNotMatch errorAWS S3 - 从 getSignedUrl() PUT 到 URL 返回 403 SignatureDoesNotMatch 错误
【发布时间】:2019-04-29 17:25:32
【问题描述】:

这个问题已经把我逼疯了两天了。

目标:通过 AWS Javascript SDK 中的 getSignedUrl 函数提供的预签名 URL 将图像直接从浏览器上传到 S3。

使用 getSignedUrl 生成 URL 没有任何问题。以下代码...

const params = {
  Key:         key,
  Bucket:      process.env.S3_BUCKET,
  ContentType: "image/jpeg"
};

S3.getSignedUrl("putObject", params, callback);

...产生类似:

https://s3.amazonaws.com/foobar-bucket/someImage.jpeg?AWSAccessKeyId=ACCESSKEY123&Content-Type=image%2Fjpeg&Expires=1543357053&Signature=3fgjyj7gpJiQvbIGhqWXSY40JUU%3D&x-amz-acl=private&x-amz-security-token=FQoGZXIvYXdzEDYaDPzeqKMbfgetCcZBaCL0AWftL%2BIT%2BP3tqTDVtNU1G8eC9sjl9unhwknrYvnEcrztfR9%2FO9AGD6VDiDDKfTQ9SmQpfXmiyTKDwAcevTwxeRnj6hGwnHgvzFVBzoslrB8MxrxjUpiI7NQW3oRMunbLskZ4LgvQYs8Rh%2FDjat4H%2F%2BvfPxDSQUSa41%2BFKcoySUHGh2xqfBFGCkHlIqVgk1KELDHmTaNckkvc9B4cgEXmAd3u1f1KC9mbobYcLLRPIzMj9bLJH%2BIlINylzubao1pCQ7m%2BWdX5xAZDhTSNwQfo4ywSWV7kUpbq2dgEriOiKAReEjmFQtuGqYBi3t2dhrasptOlXFXUozdz23wU%3D

但是通过 PUT 请求将图像上传到提供的 URL 总是会从 S3 返回 403 SignatureDoesNotMatch 错误。

有什么作用:

  • 从本地 AWS Lambda 实例调用 getSignedUrl()(通过无服务器离线)。

什么不起作用:

  • 将查询字符串变量设置为标题(Content-Type、x-amz-* 等)
  • 删除所有标题
  • 获取 URL 时更改 ACL(私有、公共读写、无 ACL 等)
  • 在 Node 中更改 aws-sdk 的区域
  • 尝试 POST 而不是 PUT(值得一试)

对于这个问题的任何帮助将不胜感激。如果这仍然是一个问题,我将把我的电脑扔出窗外,然后沮丧地跳出来,因为它根本不想工作!

【问题讨论】:

    标签: node.js amazon-s3 aws-lambda serverless


    【解决方案1】:

    我想通了。调用 getSignedUrl() 的 Lambda 函数没有正确的 IAM 角色权限来访问有问题的 S3 存储桶。在 serverless.yml...

    iamRoleStatements:
        - Effect: Allow
          Action:
            - s3:*
          Resource: "arn:aws:s3:::foobar-bucket/*"
    

    我实际上不会在这里使用通配符,但你明白了。 getSignedUrl() 仍然成功并返回一个 URL,即使该 URL 由于缺少权限而注定要失败,这一事实极具误导性。

    我希望这个答案对将来有些困惑的人有所帮助。

    【讨论】:

    • 非常感谢。我发现我必须为 both 我的 IAM 角色和我的存储桶权限执行权限,而不仅仅是 iam 角色
    • 谢谢。我让它在以前的测试 lambda 上工作,但是当我切换时没有给它写权限。谢谢!
    【解决方案2】:

    它以老式的方式对我有用:(axios 不断给出 403 Forbidden)

      const xhr = new XMLHttpRequest();
      xhr.open("PUT", signedRequest);
      xhr.onreadystatechange = () => {
    
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            //Put your logic here..
             //When it get's here you can access the image using the url you got when signed.
          }    
        }
      };
      xhr.send(file);
    

    请注意,这需要从客户端运行,因此您需要在 Bucket 中配置 Cross Origin Police。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-17
      • 2019-03-30
      • 2017-02-23
      • 2013-03-16
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 2016-09-03
      相关资源
      最近更新 更多