简体   繁体   中英

CORS upload file to S3, got SignatureDoesNotMatch error

I want to upload video files from browser to S3. Here is the my steps:

  1. Send GET request to API Gateway, invoke Lambda to get a signed URL.
  2. Use the signed URL directly to upload files to S3 using PUT .

Step 1 works fine, I can use the signed URL to upload file through curl :

curl -X PUT https://bucket-name.s3.amazonaws.com/testupload/videofile.mp4?AWSAccessKeyId=MY_AWS_ACCESS_KEY_ID&Expires=1523329853&Signature=XXXXX -T videophile.mp4

But upload the file to S3 from browser, I get 403 response with SignatureDoesNotMatch error:

<Error>

<Code>SignatureDoesNotMatch</Code>

<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

<AWSAccessKeyId>MY_AWS_ACCESS_KEY_ID</AWSAccessKeyId>

...

...

</Error>

I checked the access key is the one I used in lambda to create signed url


Client side Javascript:

$.ajax({
    url : signedurl,
    type : "PUT",
    data : uploadfile,
    dataType : "text",
    cache : false,
    contentType : file.type,
    processData : false
})
.done(function() {

})
.fail(function(e) {
    console.error(e.status, e.statusText)
    console.error(e.responseText)
});

Bucket CORS config:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">    
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

I found the solution. Content Type is needed when creating the signed URL and in the http request header (even when you can upload file by curl ) :

Lambda code (node):

s3.getSignedUrl('putObject', {
    Bucket: "bucket-name",
    Key: `key/filename.ext`,
    ContentType: event.contentType,  // e.g.: "video/mp4"
    Expires: 300
})

Client side JavaScript

$.ajax({
    url : signedurl,
    type : "PUT",
    data : uploadfile,
    cache : false,
    headers:{
        'Content-Type': file.type  // e.g.: "video/mp4"
    },
    processData : false
})

Useful links:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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