Java上的服务器名称指示(SNI)

Jel*_*Cat 12 java ssl http sni

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

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

所以...任何帮助?

小智 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()
Run Code Online (Sandbox Code Playgroud)

直到HTTPCLIENT-1119被修复

  • 现在已修复,可在 HttpComponents HttpClient 4.3.2 中使用。 (2认同)

shr*_*yas 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;
}
Run Code Online (Sandbox Code Playgroud)

这就是我创造的方式 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();
Run Code Online (Sandbox Code Playgroud)

  • 请不要使用`SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER`。 (2认同)