Amazon S3 Signature Does Not Match - AWS SDK Java

前端 未结 8 1892
不知归路
不知归路 2021-01-01 12:18

I have a play application that needs to upload files to S3. We are developing in scala and using the Java AWS SDK.

I\'m having trouble trying to upload files, I keep

8条回答
  •  伪装坚强ぢ
    2021-01-01 13:02

    Doubt the OP still has a problem with this, but for anyone else who runs into this, here is the answer:

    When making a signed request to S3, AWS checks to make sure that the signature exactly matches the HTTP Header information the browser sent. This is unfortunately required reading: http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

    However in the code above this is not actually the case, the Javascript is sending:

    xhr.setRequestHeader('Content-Type', 'image/png');
    xhr.setRequestHeader('x-amz-acl', 'authenticated-read');
    

    But in the Java/Scala, s3.generatePresignedUrl is being called without passing in either of them. So the resulting signature is actually telling S3 to reject anything with a Content-Type or x-ams-acl header set. Oops (I fell for it too).

    I've seen browsers send Content-Types automatically, so even if they're not explicitly added to the header they could still be coming into S3. So the question is, how do we add Content-Type and x-amz-acl headers into the signature?

    There are several overloaded generatePresignedUrl functions in the AWS SDK, but only one of them allows us to pass in anything else besides the bucket-name, filename, expiration-date and http-method.

    The solution is:

    1. Create a GeneratePresignedUrlRequest object, with your bucket and filename.
    2. Call setExpiration, setContentType, etc, to set all of your header info on it.
    3. Pass that into s3.generatePresignedUrl as the only parameter.

    Here's the proper function definition of GeneratePresignedUrlRequest to use:

    http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html#generatePresignedUrl(com.amazonaws.services.s3.model.GeneratePresignedUrlRequest)

    The function's code on the AWS GitHub repo was also helpful for me to see how to code up the solution. Hope this helps.

提交回复
热议问题