【问题标题】:Server Name Indication (SNI) on JavaJava 上的服务器名称指示 (SNI)
【发布时间】:2012-09-03 20:59:27
【问题描述】:

谁能帮助我开始使用 Java 中的服务器名称指示执行 HTTP 连接?

我正在尝试从我正在管理的网站请求内容。我一直在使用 Apache 的 HttpClient 库,但我对安全内容的请求失败了,因为该网站仅将 SNI 用于 HTTPS,并且在 DefaultHttpClient 中未启用 SNI。我已经在 Apache 的 HttpClient 库中查找了有关如何处理此问题的说明,但我看到了这个文档:http://hc.apache.org/httpclient-3.x/sslguide.html,它已过时(当 HttpClient 和 HttpCore 是 Apache 的 commons 包的一部分时,请参考代码) .

那么……有什么帮助吗?

【问题讨论】:

    标签: java http ssl sni


    【解决方案1】:

    这就是我在org.apache.httpcomponents的httpclient v4.3+中的做法

    private HttpClientConnectionManager createConnectionManager(final SSLContext ctx) {
        LOG.info("Creating sslConnectionSocketFactory");
        final SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(ctx) {
    
            @Override
            protected void prepareSocket(SSLSocket socket) throws IOException {
                try {
                    System.out.println("************ setting socket HOST property *************");
                    PropertyUtils.setProperty(socket, HOST, Constants.SNI_HOST);
                } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
                    LOG.error(ex.getMessage());
                }
                super.prepareSocket(socket); 
            }
    
        };
    
        LOG.info("Creating connectionRegistry");
        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslSF)
                .build();
    
        LOG.info("Creating poolingConnectionManager");
        final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE);
        connectionManager.setMaxTotal(MAX_CONNECTIONS);
    
        return connectionManager;
    }
    

    这就是我创建HttpClient的方式

    final KeyManager[] keyManagers = createKeyManagers();
    final TrustManager[] trustManagers = createTrustManagers();
    final SSLContext ctx = createSslContext(keyManagers, trustManagers);
    
    final HttpClientConnectionManager connectionManager = createConnectionManager(ctx);
    
    LOG.info("Creating httpClient");
    HttpClient httpClient = HttpClients
            .custom()
            .setConnectionManager(connectionManager)
            .build();
    

    【讨论】:

    • 请不要使用SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
    • 对于那些可能像我一样好奇的人的一些说明:PropertyUtils 来自commons-beanutils String HOST = "host"; Constants.SNI_HOST 是您要连接的服务器的 DNS 主机名。最重要的是:httpclient 4.5.2 不再需要自定义工厂
    • @DaanReid - “不再需要定制工厂”是什么意思?有没有我们可以使用的默认实现。
    • @Shyam 如果您的 httpclient 是最新的,则默认实现开箱即用:SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext)
    • SNI 在 Java7 中工作,但是......请注意,有人可能禁用了它。您可能想要搜索jsse.enableSNIExtension。并检查是否有人将其设置为 false ?
    【解决方案2】:

    对我有用的是在 Apache 配置中正确配置 ServerName

    /etc/apache2/sites-avaible/default

    <VirtualHost *:443>
      ServerName foo.domain.com
      ...
    </VirtualHost>
    

    就像https://stackoverflow.com/a/8058839/2088282中所说的那样。

    【讨论】:

      【解决方案3】:

      具有如下所述的简短修复: TLS with SNI in Java clients 可以将 SNI 服务器支持添加到 JDK 7 并与 X509ExtendedKeyManager 一起使用。

      【讨论】:

        【解决方案4】:

        您可能想跟踪https://issues.apache.org/jira/browse/HTTPCLIENT-1119

        Java 7 的底层客户端实现能够支持它并通过 SSLSocketImpl#setHost(由 sun.net.www.protocol.https.HttpsClient 调用)公开该功能

        在 Java 7 上使用

            new URL("https://cmbntr.sni.velox.ch/").openStream()
        

        直到 HTTPCLIENT-1119 被修复

        【讨论】:

        • 现已修复,在 HttpComponents HttpClient 4.3.2 中可用。
        • 在 OpenJDK 上的 Tomcat 中使用 HttpClient 4.3.2(最高版本 1.7.0_111),SNI 仍然会失败。切换到 Oracle HotSpot (1.7.0_80) 后,SNI 工作了。对于在 AWS Beanstalk 上遇到此问题的任何人,请查看此 ebextension 以将 JVM 切换到 Oracle:gist.github.com/bremeld/6706980
        【解决方案5】:

        这个问题似乎在Java 7 中得到修复。

        【讨论】:

        • 谢谢。我认为情况确实如此。但是,RFC 没有给我任何关于如何实现这一点的提示(除非从头开始构建我自己的客户端)。对现有工具或如何为此使用 Apache HttpClient 有任何想法吗?
        猜你喜欢
        • 2017-05-23
        • 2011-07-04
        • 1970-01-01
        • 2013-11-03
        • 2016-01-03
        • 2020-05-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多