javascript Amazon S3签名不匹配- AWS SDK Java

gj3fmq9x  于 2023-11-15  发布在  Java
关注(0)|答案(7)|浏览(360)

我有一个游戏应用程序,需要上传文件到S3。我们正在scala开发,并使用Java AWS SDK。
我在尝试上传文件时遇到问题,使用预签名的URL时,我一直收到403 SignatureDoesNotMatch。该URL是使用AWS Java SDK通过以下代码生成的:

  1. def generatePresignedPutRequest(filename: String) = {
  2. val expiration = new java.util.Date();
  3. var msec = expiration.getTime() + 1000 * 60 * 60; // Add 1 hour.
  4. expiration.setTime(msec);
  5. s3 match {
  6. case Some(s3) => s3.generatePresignedUrl(bucketname, filename, expiration, HttpMethod.PUT).toString
  7. case None => {
  8. Logger.warn("S3 is not availiable. Cannot generate PUT request.")
  9. "URL not availiable"
  10. }
  11. }
  12. }

字符串
对于前端代码,我们遵循ioncannon article
上传文件的js函数(与文章中使用的相同)

  1. function uploadToS3(file, url)
  2. {
  3. var xhr = createCORSRequest('PUT', url);
  4. if (!xhr)
  5. {
  6. setProgress(0, 'CORS not supported');
  7. }
  8. else
  9. {
  10. xhr.onload = function()
  11. {
  12. if(xhr.status == 200)
  13. {
  14. setProgress(100, 'Upload completed.');
  15. }
  16. else
  17. {
  18. setProgress(0, 'Upload error: ' + xhr.status);
  19. }
  20. };
  21. xhr.onerror = function()
  22. {
  23. setProgress(0, 'XHR error.');
  24. };
  25. xhr.upload.onprogress = function(e)
  26. {
  27. if (e.lengthComputable)
  28. {
  29. var percentLoaded = Math.round((e.loaded / e.total) * 100);
  30. setProgress(percentLoaded, percentLoaded == 100 ? 'Finalizing.' : 'Uploading.');
  31. }
  32. };
  33. xhr.setRequestHeader('Content-Type', 'image/png');
  34. xhr.setRequestHeader('x-amz-acl', 'authenticated-read');
  35. xhr.send(file);
  36. }
  37. }


服务器的响应是

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Error><Code>SignatureDoesNotMatch</Code>
  3. <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
  4. <StringToSignBytes>50 55 bla bla bla...</StringToSignBytes>
  5. <RequestId>F7A8F1659DE5909C</RequestId>
  6. <HostId>q+r+2T5K6mWHLKTZw0R9/jm22LyIfZFBTY8GEDznfmJwRxvaVJwPiu/hzUfuJWbW</HostId>
  7. <StringToSign>PUT
  8. image/png
  9. 1387565829
  10. x-amz-acl:authenticated-read
  11. /mybucketname/icons/f5430c16-32da-4315-837f-39a6cf9f47a1</StringToSign>
  12. <AWSAccessKeyId>myaccesskey</AWSAccessKeyId></Error>


我已经配置了CORS,仔细检查了AWS凭据,并尝试更改请求头。我总是得到相同的结果。为什么亚马逊告诉我签名不匹配?

vddsk6oq

vddsk6oq1#

怀疑OP仍然有这个问题,但对于任何遇到这个问题的人来说,这里是答案:
当向S3发出签名请求时,AWS会进行检查,以确保签名与浏览器发送的HTTP Header信息完全匹配。不幸的是,这需要阅读:http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
然而,在上面的代码中,实际情况并非如此,JavaScript正在发送:

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

字符串
但是在Java/Scala中,s3.generatePresignedUrl被调用时没有传入任何一个。所以结果签名实际上是告诉S3拒绝任何带有Content-Type或x-ams-acl头集的东西。哎呀(我也上当了)。
我见过浏览器自动发送Content-Type,所以即使它们没有显式地添加到头部,它们仍然可以进入S3。所以问题是,我们如何将Content-Type和x-amz-acl头部添加到签名中?
在AWS SDK中有几个重载的generatePresignedUrl函数,但其中只有一个允许我们传入除bucket-name、filename、recruitation-date和http-method之外的任何其他内容。
解决方案是:
1.创建一个GeneratePresignedUrlRequest对象,包含你的bucket和文件名。
1.调用setString、setContentType等来设置所有的头信息。
1.将其作为唯一参数传递给s3.generatePresignedUrl。
下面是要用途:使用的GeneratePresignedUrlRequest的正确函数定义:
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html#generatePresignedUrl(com.amazonaws.services.s3.model.GeneratePresignedUrlRequest)
AWS GitHub存储库上的函数代码也有助于我了解如何编写解决方案。希望这对您有所帮助。

展开查看全部
smdncfj3

smdncfj32#

我也遇到过类似的问题,在我的情况下,设置配置signatureVersion: 'v4'帮助解决了这个问题-
在JavaScript中:

  1. var s3 = new AWS.S3({
  2. signatureVersion: 'v4'
  3. });

字符串
改编自https://github.com/aws/aws-sdk-js/issues/902#issuecomment-184872976

goucqfw6

goucqfw63#

我刚刚在使用NodeJs AWS SDK时遇到了这个问题。这是由于使用了有效的凭据,* 但没有足够的权限。* 更改为我的管理员密钥解决了这个问题,而没有更改代码!编辑:管理员密钥是一个极端的测试示例;在真实的生活中,当然要遵循密钥管理和最小权限的最佳实践。

mftmpeh8

mftmpeh84#

我也遇到了同样的问题,但删除内容类型工作正常。特此分享完整的代码。

  1. public class GeneratePresignedUrlAndUploadObject {
  2. private static final String BUCKET_NAME = "<YOUR_AWS_BUCKET_NAME>";
  3. private static final String OBJECT_KEY = "<YOUR_AWS_KEY>";
  4. private static final String AWS_ACCESS_KEY = "<YOUR_AWS_ACCESS_KEY>";
  5. private static final String AWS_SECRET_KEY = "<YOUR_AWS_SECRET_KEY>";
  6. public static void main(String[] args) throws IOException {
  7. BasicAWSCredentials awsCreds = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
  8. AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1)
  9. .withCredentials(new AWSStaticCredentialsProvider(awsCreds)).build();
  10. try {
  11. System.out.println("Generating pre-signed URL.");
  12. java.util.Date expiration = new java.util.Date();
  13. long milliSeconds = expiration.getTime();
  14. milliSeconds += 1000 * 60 * 60;
  15. expiration.setTime(milliSeconds);
  16. GeneratePresignedUrlRequest generatePresignedUrlRequest =
  17. new GeneratePresignedUrlRequest(BUCKET_NAME, OBJECT_KEY);
  18. generatePresignedUrlRequest.setMethod(HttpMethod.PUT);
  19. generatePresignedUrlRequest.setExpiration(expiration);
  20. URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
  21. UploadObject(url);
  22. System.out.println("Pre-Signed URL = " + url.toString());
  23. } catch (AmazonServiceException exception) {
  24. System.out.println("Caught an AmazonServiceException, " +
  25. "which means your request made it " +
  26. "to Amazon S3, but was rejected with an error response " +
  27. "for some reason.");
  28. System.out.println("Error Message: " + exception.getMessage());
  29. System.out.println("HTTP Code: " + exception.getStatusCode());
  30. System.out.println("AWS Error Code:" + exception.getErrorCode());
  31. System.out.println("Error Type: " + exception.getErrorType());
  32. System.out.println("Request ID: " + exception.getRequestId());
  33. } catch (AmazonClientException ace) {
  34. System.out.println("Caught an AmazonClientException, " +
  35. "which means the client encountered " +
  36. "an internal error while trying to communicate" +
  37. " with S3, " +
  38. "such as not being able to access the network.");
  39. System.out.println("Error Message: " + ace.getMessage());
  40. }
  41. }
  42. public static void UploadObject(URL url) throws IOException
  43. {
  44. HttpURLConnection connection=(HttpURLConnection) url.openConnection();
  45. connection.setDoOutput(true);
  46. connection.setRequestMethod("PUT");
  47. OutputStreamWriter out = new OutputStreamWriter(
  48. connection.getOutputStream());
  49. out.write("This text uploaded as object.");
  50. out.close();
  51. int responseCode = connection.getResponseCode();
  52. System.out.println("Service returned response code " + responseCode);
  53. }
  54. }

字符串

展开查看全部
m0rkklqb

m0rkklqb5#

有一个问题,windows上的mime类型将fileType设置为空字符串,它不起作用。只需处理空字符串并添加一些文件类型。

atmip9wb

atmip9wb6#

我在使用Java AWS SDK时遇到了SignatureDoesNotMatch错误。在我的例子中,在升级maven依赖项而不更改代码后发生了SignatureDoesNotMatch错误。(因此凭据是正确的,没有被更改)。将依赖项org.apache.httpcomponents:httpclient从版本4.5.6升级到4.5.7后(实际上是Spring Boot2.1.2升级到2.1.3bom已经指定了httpclient版本),代码在执行一些AWS SDK S3请求(如AmazonS3.getObject)时成为抛出异常。
在深入挖掘根本原因后,我发现httpclient库使用规范化URI进行了破坏性更改,影响了Java AWS SDK S3。请查看打开的GitHub ticket org.apache.httpcomponents:httpclient:4.5.7 breaks fetching S3 objects以了解更多详细信息。

piwo6bdm

piwo6bdm7#

如果您的访问密钥和密钥都是正确的,但它显示“SignatureDoesNotmatch”,请检查您的密钥,它可能具有某些特殊字符,例如+/ - / *
转到aws并生成另一个访问密钥,其中密钥没有这些。然后再试一次:)

相关问题