使用 Java API 的 S3/AWS 的 SSL 问题:"hostname in certificate didn't match"



亚马逊在1.3.21版本中"升级"了其AWS Java SDK中的SSL安全性。这破坏了在使用亚马逊的AWS Java API时访问任何名称中有句点的S3存储桶。我使用的是1.3.21.1版本,最新版本为2012年10月5日。我在下面的回答中提供了一些解决方案,但我正在寻找解决这个问题的其他方法。

如果您收到此错误,您将在异常/日志中看到类似以下消息的内容。在本例中,bucket名称为foo.example.com

INFO: Unable to execute HTTP request: hostname in certificate didn't match:
<foo.example.com.s3.amazonaws.com> != <*.s3.amazonaws.com>
OR <*.s3.amazonaws.com> OR <s3.amazonaws.com>
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)
at org.apache.http.conn.ssl.StrictHostnameVerifier.verify(StrictHostnameVerifier.java:61)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:390)

你可以在AWS S3讨论论坛上看到这个问题的文档:

https://forums.aws.amazon.com/thread.jspa?messageID=387508&387508

亚马逊对此问题的回应如下。

我们应该能够通过对具有此命名模式的bucket使用较旧的路径样式的bucket寻址方法(而不是较新的虚拟主机样式的寻址)来解决此问题。我们将开始修复,并确保我们的内部集成测试具有包含句点的bucket名称的测试用例。

是否有变通方法或其他解决方案?感谢您的反馈。

原件:2012年10月

原来亚马逊;升级的";2012年9月下旬S3上的SSL安全。这破坏了在使用亚马逊的AWS Java API时访问任何名称中有句点的S3存储桶。

这是不准确的。S3的SSL通配符匹配与2006年推出S3时相同。更有可能的是,AWS Java SDK团队启用了对SSL证书的更严格验证(好),但最终破坏了与S3的SSL证书冲突的存储桶名称(坏)。

正确的答案是,您需要使用路径样式寻址,而不是DNS样式全方法。禁用验证会使您面临中间人攻击。

我目前不知道的是,Java SDK是否将其作为一个可配置选项提供。如果是,那就是你的答案。否则,听起来Java SDK团队会说";我们将添加此功能,然后添加集成测试以确保一切正常">

更新:2020年10月

AWS宣布,路径式寻址已被弃用,并将在不久的将来消失。AWS的建议是使用DNS兼容的bucket名称,这意味着没有句点(以及其他一些东西)。S3的某些更新功能需要DNS兼容的存储桶名称(例如,加速传输)。

如果你需要一个包含句点的bucket名称(在不久的将来,新bucket也不允许使用句点),如果你想通过HTTPS访问它,我最好的建议是在它前面放一个CloudFront分发版。

亚马逊发布了1.3.22版本,解决了这个问题。我已经验证了我们的代码现在可以工作了。引用他们的发行说明:

名称中包含句点的Buckets现在可以通过HTTPS再次正确寻址。

除了等待亚马逊发布新的API之外,我还可以看到一些解决方案。

  1. 显然,您可以回滚到AWS Java SDK的1.3.20版本。不幸的是,我需要1.3.21中的一些功能。

  2. 您可以替换类路径中的org.apache.http.conn.ssl.StrictHostnameVerifier。然而,这是一个破解,我认为它将删除Apache http连接的所有SSL检查。以下是适用于我的代码:http://pastebin.com/bvFELdJE

  3. 我最终从AWS源jar下载并构建了自己的包。我对HttpClientFactory源应用了以下近似补丁。

    ===================================================================
    --- src/main/java/com/amazonaws/http/HttpClientFactory.java     (thirdparty/aws)      (revision 20105)
    +++ src/main/java/com/amazonaws/http/HttpClientFactory.java     (thirdparty/aws)    (working copy)
    @@ -93,7 +93,7 @@
    SSLSocketFactory sf = new SSLSocketFactory(
    SSLContext.getDefault(),
    -                               SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
    +                               SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
  4. 正确的解决方案是从域名存储桶处理改为基于路径的处理。

顺便说一句,下面的内容看起来可能有效,但它确实有效。AWS客户端特别请求STRICT验证器,并且不使用默认验证器:

SSLSocketFactory.getSystemSocketFactory().setHostnameVerifier(
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

最新更新