AWS Java SDK 2.0中的S3预签名URL公开对象访问。

huangapple go评论87阅读模式
英文:

AWS Java SDK 2.0 S3 presigned URL public object access

问题

在自身创建预签名 URL 进行文件上传方面是正常工作的。
但是通过默认生成的 URL 上传文件会使其默认为私有,因此无法通过其 URL 访问。

我必须手动转到控制台,将文件设置为公开,才能通过其 URL 访问。

以下是您的代码:

String bucketName = "<bucket-name>";
String keyName = "<file-name>";

S3Presigner presigner = S3Presigner.builder().region(Region.AP_SOUTH_1).build();

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .build();

PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(3))
        .putObjectRequest(objectRequest)
        .build();

PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);

System.out.println("上传文件的预签名 URL: " +
        presignedRequest.url());
System.out.println("上传文件时需要使用的 HTTP 方法: " +
        presignedRequest.httpRequest().method());	

presigner.close();

在 Node.js 中,我们指定希望文件可以公开访问,因此我找到了其 Java SDK 的等效代码,如下所示:

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .acl(ObjectCannedACL.PUBLIC_READ)
        .build();

但是,通过生成的 URL 进行上传时,我收到了签名不匹配的错误:

我们计算的请求签名与您提供的签名不匹配。请检查您的密钥和签名方法。

我做错了什么?难道这不是使文件公开访问的正确方法吗?如果不是,我应该如何操作?

英文:

Creating presigned url for file upload in itself is working fine.
But uploading the file through the generated URL by default makes it private and hence cannot be accessed through it's URL

I have to manually go to the console and make the file public to be accessible from it's URL

Here is my code

String bucketName = &quot;&lt;bucket-name&gt;&quot;;
String keyName = &quot;&lt;file-name&gt;&quot;;

S3Presigner presigner = S3Presigner.builder().region(Region.AP_SOUTH_1).build();

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .build();

PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(3))
        .putObjectRequest(objectRequest)
        .build();

PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);

System.out.println(&quot;Pre-signed URL to upload a file to: &quot; +
        presignedRequest.url());
System.out.println(&quot;Which HTTP method needs to be used when uploading a file: &quot; +
        presignedRequest.httpRequest().method());	

presigner.close();

In NodeJs we specify that we want the file to be publicly accessible so I found it's java sdk equivalent like this

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .acl(ObjectCannedACL.PUBLIC_READ)
        .build();

But when uploading through the URL thus generated, I'm getting a singature mismatch error

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

What am I doing wrong? Is it not the correct way to make the file publicly accessible? If not, how should I do it?

答案1

得分: 2

我在AWS的java-sdk的GitHub页面上发布了相同的问题,并找到了解决方案。

PutObjectRequest.builder()中添加.acl(ObjectCannedACL.PUBLIC_READ)将在标头中添加x-amz-acl,而不是在需要的查询中添加。

以下是如何在查询中添加它的方式:

AwsRequestOverrideConfiguration override = AwsRequestOverrideConfiguration.builder()
        .putRawQueryParameter("x-amz-acl", "private")
        .build();

PutObjectRequest putObjectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .overrideConfiguration(override)
        .build();

这个解决方案完美地解决了问题。希望能对其他人有所帮助。

欲了解更多信息,请参阅github链接

英文:

I posted the same question on AWS's github for java-sdk and found the solution.

Adding .acl(ObjectCannedACL.PUBLIC_READ) in PutObjectRequest.builder() will add x-amz-acl in the header as opposed to the query where it is needed

Here's how to add it in the query

AwsRequestOverrideConfiguration override = AwsRequestOverrideConfiguration.builder()
        .putRawQueryParameter(&quot;x-amz-acl&quot;, &quot;private&quot;)
        .build();

PutObjectRequest putObjectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .overrideConfiguration(override)
        .build();

The solution works perfectly. Thought it might help someone else as well

For more info, see github

答案2

得分: 0

这应该可以解决问题:

new PutObjectRequest("xxx", "xxx", fis, metadata).withCannedAcl(CannedAccessControlList.PublicRead));
英文:

This should do the trick:

new PutObjectRequest(&quot;xxx&quot;, &quot;xxx, fis, metadata).withCannedAcl(CannedAccessControlList.PublicRead));

huangapple
  • 本文由 发表于 2020年9月22日 19:19:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/64008628.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定