当前位置: 首页 > 知识库问答 >
问题:

AWS S3 - 来自 getSignedUrl() 的 PUT to URL 返回 403 SignatureDoesNotMatch 错误

卓雅达
2023-03-14

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

目标:通过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

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

什么工作:

  • 从AWS Lambda的本地实例调用getSignedUrl()(通过无服务器脱机)

什么不起作用:

  • 将查询字符串变量设置为标头(内容类型、x-amz-* 等)
  • 删除所有标头
  • 获取 URL 时更改 ACL(私有、公共读写、无 ACL 等)
  • 在节点中更改 aws-sdk 的区域
  • 尝试开机自检而不是推杆(值得一试)

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


共有2个答案

尤夕
2023-03-14

它以老派的方式为我工作:(axios 不断给出 403 禁止)

  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。

廖夜洛
2023-03-14

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

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

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

我希望这个答案在未来能帮助一些困惑的灵魂。

 类似资料:
  • 我有一条可以观察到的溪流。第一个运算符是一个mergeMap,它返回一个可观察的数组。然后,我必须有第二个mergeMap从第一个mergeMap的返回中获取最终值。我觉得这第二个合并映射应该是不必要的,但找不到绕过它的方法。 例子: 这最终是我所拥有的。第二个mergeMap只存在于订阅第一个的输出。没有它,我的输出是可观察的(即(1)的

  • 我想这样做: js中是否有一种方法可以调用同步代码中的函数,并仅在我的controlVar变为1时返回值? 这不应该阻止,因为当我使用setTimeout时,主循环应该能够控制,但是如果阻止对我来说并不重要。 谢谢

  • 问题内容: 我有一种感觉,我在这里做错了什么,但是我不确定是错过了一步,还是遇到编码问题或其他问题。这是我的代码: 当我打印内容时,我会得到一大堆的装饰物和特殊字符,基本上是乱码。我会在这里复制并粘贴它,但这不起作用。我究竟做错了什么? 问题答案: 在这种情况下,这不是字符编码问题,而是内容编码问题。您正在等待文本,但是服务器使用压缩来节省带宽。如果在获取该URL时查看标题,则可以看到您连接的服务

  • 我知道显示输出的其他方式。但我想知道是否可以直接检索返回数组的元素。

  • 基类控制器里有error方法,用于api的错误消息返回输出 /** * 操作错误跳转的快捷方法 * @access protected * @param mixed $msg 提示信息,若要指定错误码,可以传数组,格式为['code'=>您的错误码,'msg'=>'您的错误消息'] * @param mixed $data 返回的数据 * @par

  • 问题内容: 我没有任何例外,但是当我跑步时… 然后,deckFile.read()返回-1。该文件位于正确的文件夹中,并且不为空。 这应该是世界上最容易的事情。 编辑:AssetManager实际上确实在那里列出“ cards.txt”,所以这不应该是问题。 问题答案: 问题是我的文件太大,并且由于扩展名为“ .txt”而被压缩了。通过将文件重命名为通常已压缩的格式“ .mp3”,就没有问题

  • 此页返回一个空摘要: https://fr.wikipedia.org/w/api.php?action=query 但同样的查询适用于其他页面:https://fr.wikipedia.org/w/api.php?action=query 添加“ 我做错什么了吗?

  • 我有一个带有@Controller的SpringBoot应用程序,它接受对localhost:8080/all的getRequest并返回JSON。我已经在浏览器中输入了这个域,并看到了返回的JSON。 但是,当我尝试使用来自我的React应用程序(在本地运行)的Axios get请求点击此url时,而不是返回JSON数据,它会返回以下错误: 我检查了Chrome的网络选项卡中的get请求,它没有