简体   繁体   English

对 AWS 预签名 url 的 PUT 请求的 SignatureDoesNotMatch

[英]SignatureDoesNotMatch on PUT request for AWS presigned url

There are a number of questions/answer related to this, but they do not seem to apply to my situation or the answer does not appear to solve this.有许多与此相关的问题/答案,但它们似乎不适用于我的情况,或者答案似乎无法解决这个问题。

I have a AWS lambda function that returns a getSignedUrl generated by this function: getUploadURL我有一个 AWS lambda function ,它返回由这个getSignedUrl生成的 getSignedUrl: getUploadURL

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`
      })
    })
  })
}

My intention is that this generates a URL (ie, uploadURL ), to which I can post/put/send a csv file, and that this csv is then automatically saved at s3 bucket uploadBucket .我的意图是,这会生成一个 URL (即uploadURL ),我可以将 csv 文件发布/放置/发送到该文件,然后此uploadBucket会自动保存在存储桶上传桶 3。 I have an AWS API gateway pointing towards this function with a specific url endpoint.我有一个 AWS API 网关指向这个 function 和一个特定的 url 端点。 I can send a jquery GET request to this API endpoint, and it will return the uploadURL .我可以向这个 API 端点发送一个 jquery GET 请求,它会返回uploadURL

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

Here req.response text appears to be correct:这里req.response文本似乎是正确的:

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

Then, I have some text/csv data, which I intend to send to the uploadURL然后,我有一些text/csv数据,我打算将其发送到uploadURL

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

At first I tried a simple request (below), but this return an SignatureDoesNotMatch error.起初我尝试了一个简单的请求(如下),但这会返回一个SignatureDoesNotMatch错误。

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

Based on what I understand, this is caused by the ajax put paramaters not matching the lambda s3Params .根据我的理解,这是由 ajax put 参数与 lambda s3Params不匹配引起的。 I tried to add contentType:'text/csv', and a key:csvFileName .我尝试添加contentType:'text/csv',key:csvFileName I tried to send it as a blob , and as a formdata, but all to no success.我试图将它作为blob和 formdata 发送,但都没有成功。

What do I need to change so I no longer get the SignatureDoesNotMatch and can succesfully upload a csv to a bucket?我需要更改什么才能不再获得SignatureDoesNotMatch并且可以成功地将 csv 上传到存储桶?

First of all, in my case I wanted to send a csv.首先,就我而言,我想发送一个 csv。 I decided it'd be easier to send a.txt file, and then read it as csv.我决定发送一个 .txt 文件会更容易,然后将其读取为 csv。 This made me change my content-type to 'txt'.这使我将内容类型更改为“txt”。

Besides this, I needed to have my bucket configured to (also) contain:除此之外,我需要将我的存储桶配置为(也)包含:

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

Next, in my ajax put request, it should read:接下来,在我的 ajax 放置请求中,它应该是:

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

For me, setting the signature version when creating the S3 object fixed the problem.对我来说,在创建 S3 object 时设置签名版本解决了这个问题。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM