【问题标题】:Generate Presigned URL with format: s3.amazonaws.com/bucket.name生成格式为:s3.amazonaws.com/bucket.name 的预签名 URL
【发布时间】:2016-03-29 05:25:24
【问题描述】:

我正在生成预签名的 url,但由于 *.s3.amazonaws 证书,它对于带有句点和 SSL 的存储桶名称存在问题,如下所述: http://shlomoswidler.com/2009/08/amazon-s3-gotcha-using-virtual-host.html

有没有办法生成以下格式的网址?: http://s3.amazonaws.com/bucket.name/key

我没有在 API 中看到选项。我猜我可以通过重新排列网址来“手动”完成,但如果没有必要,我宁愿避免黑客攻击。

根据迈克尔的回答,这里是我现在使用的代码:

public static URL bucketNameAfterS3Url(URL url) {

    int index = url.getHost().indexOf("s3");
    String host = url.getHost().substring(index);
    String bucket = url.getHost().substring(0, index - 1);
    URL toUse;
    try {
        toUse = new URL(url.getProtocol(), host, url.getPort(), '/' + bucket + url.getFile());
    } catch (MalformedURLException e) {
    }
    return toUse;
}

【问题讨论】:

  • AWS S3 文档对 getBucketLocation() 进行了说明,这是正常工作所必需的(请参阅 michael 的注释):“要查看存储桶的位置约束,用户必须是存储桶所有者。 "因为我们不拥有存储桶(我们只是获得了读取权限),所以这个解决方案似乎站不住脚,所以我们只是恢复到在周期的情况下通过我们的服务器流式传输文件。

标签: amazon-s3


【解决方案1】:

S3 客户端允许您设置一个选项来配置它:

    // Configure the S3 client to generate urls with valid SSL certificates. With this setting we will get urls
    // like https://s3.amazonaws.com/bucket_name/... but if this is not set we will get urls like
    // https://bucket_name.s3.amazonaws.com/ which will cause the browser to complain about invalid SSL
    // certificates.
    s3Client.setS3ClientOptions(new S3ClientOptions().withPathStyleAccess(true));

【讨论】:

  • 你知道这是否适用于非标准区域?
  • 不确定非标准区域是什么意思。您可以通过 s3Client.setRegion() 方法设置区域。
  • 路径样式以后会被弃用,reddit.com/r/aws/comments/bk9mfm/…你有别的解决办法吗?
  • AmazonS3ClientBuilder.standard() .withRegion(Regions.US_EAST_2) .withPathStyleAccessEnabled(true) .build();
【解决方案2】:

没有任何官方方法可以做到这一点,但字符串操作并不像看起来那么粗略,因为可能的模式是有限的。存储桶名称不能包含斜线,查找其他元素非常安全。

一个重要的考虑因素是区域,以及它如何影响 URL 的有效组合。

考虑桶“example-bucket”中的“lolcat.jpg”...

https://example-bucket.s3.amazonaws.com/lolcat.jpg
https://s3.amazonaws.com/example-bucket/lolcat.jpg

这两个 url 是等效的只有如果存储桶在美国标准区域。

如果没有,顶部的可以工作,但底部的会返回一条错误消息,告诉您您使用了错误的端点。

对于其他区域,您必须使用正确的区域端点。如果是 us-west-2,这实际上是:

https://s3-us-west-2.amazonaws.com/example-bucket/lolcat.jpg

因此,在转置 URL 中的元素之前,您必须知道存储桶的区域。

如果您使用的是签名版本 4,那么您已经知道该区域,因为生成签名需要它。使用签名版本 2,您甚至可以在签署 URL 之后重新排列存储桶名称在 URL 中的位置,而不会使签名无效,因为该算法的详细信息。

【讨论】:

  • 我不知道我们的客户在哪些地区托管他们的存储桶,所以这听起来有问题。实际上,如果我操纵了 url,我会先请求一个预签名的,然后重新排列它,但是从你说的角度来看,这听起来就像是有问题的区域......亚马逊不必将区域限定的 url 传回。感谢您提醒我地区问题,我不会意识到这是一个问题。
  • 我们可能只会告诉我们的客户不要在他们的存储桶名称中使用句点。由于这个原因,亚马逊允许这样做似乎很奇怪。
  • @Joel 允许使用点的原因是,如果不使用 HTTPS,那么您可以 CNAMEexample-bucket.example.com -> example-bucket.example.com.s3。 amazonaws.com 和 S3 将从 Host: HTTP 标头中获取存储桶名称。对于 S3 static web site hosting 功能,这同样适用,具有不同的 CNAME 目标...存储桶名称必须与完全限定的主机名匹配。大部分问题可能与 S3 多年来的发展方式有关。
  • 另外,您可以询问 S3 以 了解 存储桶的位置,在此答案中进行了解释:stackoverflow.com/questions/27091816/…
  • 我希望这不会让人觉得我不感谢您的帮助,但是这 一个 hack 或者更好地称为“解决方法”。亚马逊返回一个他们知道的 url 的事实不可能工作,即使他们有信息可以使它正确(他们有存储桶名称,他们知道它有句点,他们知道它属于哪个区域,他们知道他们正在返回 SSL 网址...)。他们真的应该解决这个问题。不是您的错,感谢您帮助解决他们的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2019-12-14
  • 2016-12-14
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
相关资源
最近更新 更多