Указание имени сервера (SNI) на Java
может ли кто-нибудь помочь мне начать работу по выполнению HTTP-соединений с указанием имени сервера в Java?
Я пытаюсь запроса контента с сайта я adminstering. Я использую библиотеку HttpClient Apache, но мой запрос на безопасный контент не выполняется, потому что веб-сайт использует только SNI для HTTPS, а SNI не включен в DefaultHttpClient. Я искал инструкцию о том, как подойти к этому в библиотеке HttpClient Apache, но я вижу, что в конечном итоге этот документ: http://hc.apache.org/httpclient-3.x/sslguide.html, который устарел (ссылаясь на код, когда HttpClient и HttpCore были частью пакета Apache commons).
Так... любой помочь?
5 ответов
возможно, вы захотите отслеживать https://issues.apache.org/jira/browse/HTTPCLIENT-1119
базовая клиентская реализация Java 7 способна поддерживать ее и предоставляет функцию через SSLSocketImpl#setHost (вызывается sun.сеть.www.протокол.https.HttpsClient
на Java 7 Используйте
new URL("https://cmbntr.sni.velox.ch/").openStream()
пока не будет исправлен HTTPCLIENT-1119
вот как я это сделал в орг.апаш.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();
с коротким исправлением, как описано ниже: TLS с SNI в Java-клиентах Можно добавить поддержку SNI-сервера в JDK 7 и использовать ее вместе с X509ExtendedKeyManager.
что сработало для меня, так это настройка ServerName
правильно в конфигурации Apache:
/etc/apache2/sites-avaible/default
<VirtualHost *:443>
ServerName foo.domain.com
...
</VirtualHost>
как сказано в https://stackoverflow.com/a/8058839/2088282.