SignatureDoesNotMatch 对 AWS 预签名网址的 PUT 请求

时间:2021-01-24 17:48:17

标签: jquery amazon-web-services aws-lambda put pre-signed-url

有许多与此相关的问题/答案,但它们似乎不适用于我的情况,或者答案似乎无法解决此问题。

我有一个 AWS lambda 函数,它返回由该函数生成的 getSignedUrlgetUploadURL

const getUploadURL = async function() {
  console.log('getUploadURL started')
  let actionId = Date.now()

  var s3Params = {
    Bucket: uploadBucket,
    Key:  `${actionId}.csv`,
    ContentType: 'text/csv',
  };

  return new Promise((resolve, reject) => {
    // Get signed URL
    let uploadURL = s3.getSignedUrl('putObject', s3Params)
    resolve({
      "statusCode": 200,
      "isBase64Encoded": false,
      "headers": {
        "Access-Control-Allow-Origin": "*"
      },
      "body": JSON.stringify({
          "uploadURL": uploadURL,
          "csvFileName": `${actionId}.csv`
      })
    })
  })
}

我的目的是生成一个 URL(即 uploadURL),我可以向其发布/放置/发送 csv 文件,然后该 csv 会自动保存在 s3 存储桶 uploadBucket .我有一个 AWS API 网关,该网关使用特定的 url 端点指向此函数。我可以向这个 API 端点发送一个 jquery GET 请求,它会返回 uploadURL

var req = $.ajax({ 
      method:"GET",
      url:url_endpoint, // the API Gateway endpoint that points towards the lambda running `getUploadURL`
    });

此处 req.response 文本似乎是正确的:

{"uploadURL":"https://materialcomv2.s3.eu-central-1.amazonaws.com/very_long_url","csvFileName":"1611509250475.csv"}

然后,我有一些 text/csv 数据,我打算将其发送到 uploadURL

data = "111,222,333\naaa,bbb,ccc\nAAA,BBB,CCC". 

起初我尝试了一个简单的请求(如下),但这返回了一个 SignatureDoesNotMatch 错误。

req= $.ajax({
      url: target_url, // this is the `uploadURL`
      method:"put", 
      data:data, // this is the csv data
    })

根据我的理解,这是由 ajax put 参数与 lambda s3Params 不匹配造成的。我尝试添加 contentType:'text/csv',key:csvFileName。我尝试将它作为 blob 和表单数据发送,但都没有成功。

我需要更改什么才能不再获得 SignatureDoesNotMatch 并且可以成功地将 csv 上传到存储桶?

2 个答案:

答案 0 :(得分:0)

首先,就我而言,我想发送一个 csv。我决定发送一个 .txt 文件会更容易,然后将其作为 csv 读取。这让我将内容类型更改为“txt”。

除此之外,我还需要将存储桶配置为(也)包含:

 "AllowedHeaders": [
      "*"
  ],
  "AllowedMethods": [
      "GET",
      "PUT"
  ]

接下来,在我的 ajax put 请求中,它应该是:

$.ajax({
      url: uploadURL, 
      type: "put",  // I originally had method:"put", which was failing. 
      data: data,   // Data here is just a string
      contentType: 'text',
    })

答案 1 :(得分:0)

对我来说,在创建 S3 对象时设置签名版本解决了这个问题。

const s3 = new AWS.S3({
  signatureVersion: "v4",
});