S3 预签名 URL 文件上传失败,使用安全/https URL

san*_*tel 2 java amazon-s3

我有两个存储桶,一个是私有的,一个是公共的。私人将拥有带有 CannedAccessControlList.Private 的文件,而公共将拥有带有 CannedAccessControlList.PublicRead 的文件。除了这些,它们都是一样的。

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



AmazonS3 s3client = new AmazonS3Client(new BasicAWSCredentials(AWS_ACCESS_KEY,AWS_SECRET_KEY));
            generatePresignedUrlRequest = new GeneratePresignedUrlRequest(AWS_BUCKET_PRIVATE_NAME, path,HttpMethod.PUT);
            generatePresignedUrlRequest.setExpiration(expiration); 
            generatePresignedUrlRequest.putCustomRequestHeader("x-amz-acl", CannedAccessControlList.Private.toString());
            generatePresignedUrlRequest.putCustomRequestHeader("content-type", fileType);
            url = s3client.generatePresignedUrl(generatePresignedUrlRequest);
Run Code Online (Sandbox Code Playgroud)

我可以在以下场景中将文件上传到 s3。默认情况下,所有生成的 URL 都是 https。1. 带有 https 的私有存储桶 2. 公共存储桶通过 https 失败,将 https 替换为 http 就可以了。

为什么公共存储桶上传失败 https 的问题。我无法在生产系统上使用 http,因为它安装了 ssl。

san*_*tel 5

我学到了两件事。

  1. S3有两种不同的书写风格,URL Path风格和虚拟主机风格。(当您的存储桶看起来像主机名时,您必须小心)

虚拟主机风格

https://xyz.com.s3.amazonaws.com/myObjectKey

路径样式

https://s3.amazonaws.com/xyz.com/myObjectKey

如果您在 https 上,上传文件的 Ajax 调用在第一种情况下会失败,因为 SSL 证书仅对 s3.amazonaws.com 有效,并且如果存储桶名称(如主机名)SSL 检查将失败并阻止 ajax 上传调用。

在 Java 中解决此问题

s3client.setS3ClientOptions(new S3ClientOptions().withPathStyleAccess(true));
Run Code Online (Sandbox Code Playgroud)
  1. 我仍然无法弄清楚 S3client 如何为 URL 形成选择哪个区域,但我发现有一段时间它会选择正确的“s3-ap-southeast-1.amazonaws.com”,有时它会选择“s3.amazonaws.com” ”。

在稍后的情况下,您上传​​将再次失败并提到 CORS 问题,如果您预签名的 URL 是 s3.amazonaws.com,并且即使您在存储桶中启用了 CORS,它也不会选择“访问控制允许来源”。因此,您需要确保使用以下代码提供正确的区域名称。

s3client.setEndpoint("s3-ap-southeast-1.amazonaws.com");//or whatever region you bucket is in.
Run Code Online (Sandbox Code Playgroud)

参考:http : //shlomoswidler.com/2009/08/amazon-s3-gotcha-using-virtual-host.html