S3预先签名的URL文件上传失败,带有安全/ https URL

时间:2016-10-15 12:30:52

标签: java amazon-s3

我有两个桶,一个是私人的,一个是公共的。 Private将拥有CannedAccessControlList.Private文件,public将拥有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);

我能够在以下场景中将文件上传到s3。默认情况下,所有生成的URL都是https。 1.私人桶与https 2.公共存储桶故障通过https,将https替换为http工作。

使用https解决公共存储桶上传失败的原因。我无法在生产系统上使用http,因为它已经安装了ssl。

2 个答案:

答案 0 :(得分:4)

我学到了两件事。

  1. S3有两种不同风格的URL路径样式和虚拟主机样式。 (当你的桶看起来像主机名时,你必须要小心)
  2. 虚拟主机风格

    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));
    
    1. 我仍然无法弄清楚S3client如何选择哪个区域进行网址形成,但我发现有一段时间它选择了正确的“s3-ap-southeast-1.amazonaws.com”,有时它会选择“s3”。 amazonaws.com”。
    2. 在以后的情况下,你上传将再次提及CORS问题,如果你预先签署的URL是s3.amazonaws.com,即使你已经在你的桶中启用了CORS,它也不会选择“Access-Control-Allow-Origin”。所以你需要make以确保使用下面的代码给出正确的区域名称。

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

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

答案 1 :(得分:0)

我通过在存储桶中创建一个文件夹来解决此问题, 为"my-bucket"而非javax.websocket生成了预签名的url。