【问题标题】:AWS S3 - 400 Bad Request when PUTting file via pre-signed URLAWS S3 - 通过预签名 URL 放置文件时出现 400 错误请求
【发布时间】:2020-12-05 17:22:52
【问题描述】:

我的请求如下所示:

https://{my-bucket-name}.s3.amazonaws.com/{user-id}/{image-name}.jpeg?AWSAccessKeyId={key}&Content-Type=image%2Fjpeg&Expires =1597576628&签名={签名}

其中 {parts} 只是被审查,但在原始响应中看起来是正确的,就像在我正在做的教程中一样。

我已允许公共访问并设置了 CORS(这就是我首先获得要上传到的预签名 URL 的原因)以及包含以下内容的存储桶策略:

    {
        "Sid": "{sid}",
        "Action": [
            "s3:GetObject"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::{my-bucket-name}/*",
        "Principal": "*"
    }

那么可能是什么问题?

编辑:将 PutObject 添加到策略中没有帮助。我直接从 React-client 上传这样的文件:

  const upload = await axios.put(uploadConfig.data.url, file, {
    headers: {
      'Content-Type': file.type
    }
  })

然后我生成这样的预签名 URL(注意 putObject 操作):

    s3.getSignedUrl('putObject', {
        Bucket: '{my-bucket-name}',
        ContentType: 'image/jpeg',
        Key: key
    }, (err, url) => res.send({key, url}));

中间件/浏览器设置的额外请求头有:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en,de;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 104221
Content-Type: image/jpeg
Host: {my-bucket-name}.s3.amazonaws.com
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/blogs/new
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla....

【问题讨论】:

  • 如何上传带有预签名 url 的文件?
  • @Phil,我已经删除了我的答案。那是错的。因为你永远不应该允许公共写访问。如果用于生成预签名 url 的 IAM 凭证有足够的权限上传文件,则预签名 url 应该也可以工作。
  • 另外,如果您的预签名 URL 是为 getObject 生成的,则无法使用该预签名 URL 执行 putObject 操作
  • @ArunK 我正在做这个教程:udemy.com/course/advanced-node-for-developers 老师解释说公共访问是好的,因为我们希望从客户端直接上传,而不浪费后端的 CPU 时间,期间上传。对我来说,这似乎是合理的,只要您只检查文件扩展名并且不进行深度文件检查。
  • 我的意思是,为存储桶策略中的每个人授予putObject 权限是不好的。使用预签名的 url 上传是正确的方法。如果您愿意与全世界共享您的文件,那么公开阅读是可以的。

标签: amazon-web-services amazon-s3


【解决方案1】:

Please use AWS4-HMAC-SHA256. 错误信息建议使用签名版本 v4。看来预签名网址中生成的签名不是v4。可能是签名版本 v2

请尝试在生成 URL 时指定签名版本,如下所示。

const s3 = new AWS.S3({signatureVersion: 'v4'})

还要确保您使用的 aws-sdk 版本高于 2.68.0,根据 to the documentation

【讨论】:

  • 谢谢,现在可以使用了。我自己搞定的 v4,但包更新为我节省了一些时间 :) 我必须添加的另一件事是自定义区域:new AWS.S3({ accessKeyId, secretAccessKey, signatureVersion: 'v4', region: 'eu-central-1' });
  • 是的,您已经了解了 V4。发布答案以帮助处于相同情况的其他人。如果您愿意,请发布答案。
  • 不不,没关系,就像我说的,你帮了我很多,感谢你:)
猜你喜欢
  • 2019-10-31
  • 2022-07-16
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 2018-02-02
  • 2019-04-18
相关资源
最近更新 更多