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

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

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

所以…任何帮助?

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

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

在Java 7上使用

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

直到HTTPCLIENT-1119被修复

这就是我在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 registry = RegistryBuilder.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(); 

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

对我ServerName是在Apache配置中正确配置ServerName

/etc/apache2/sites-avaible/default

  ServerName foo.domain.com ...  

如在https://stackoverflow.com/a/8058839/2088282中所述。

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