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中已得到修复。