13

任何人都可以帮助我开始使用 Java 中的服务器名称指示执行 HTTP 连接吗?

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

那么……有什么帮助吗?

4

5 回答 5

11

您可能想跟踪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 被修复

于 2012-10-25T02:20:23.817 回答
5

这就是我在 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();
于 2014-08-21T15:01:56.513 回答
1

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

于 2012-12-27T10:10:17.500 回答
1

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

/etc/apache2/sites-avaible/default

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

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

于 2013-02-19T18:23:59.327 回答
0

看来这个问题已在Java 7中得到修复。

于 2012-09-11T00:23:53.193 回答