web-dev-qa-db-fra.com

Indication de nom de serveur (SNI) sur Java

Quelqu'un peut-il m'aider à commencer à établir des connexions HTTP avec indication du nom du serveur en Java?

J'essaie de demander du contenu à un site que je suis en train d'administrer. J'utilise la bibliothèque HttpClient d'Apache, mais ma demande de contenu sécurisé échoue car le site Web utilise uniquement SNI pour HTTPS, et SNI n'est pas activé dans le DefaultHttpClient. J'ai cherché des instructions sur la façon d'aborder cela dans la bibliothèque HttpClient d'Apache, mais je vois que je vais finir avec ce document: http://hc.Apache.org/httpclient-3.x/sslguide.html , qui est obsolète (référence au code à l'époque où HttpClient et HttpCore faisaient partie du paquetage commun d'Apache).

Alors ... de l'aide?

12
JellicleCat

vous voudrez peut-être suivre https://issues.Apache.org/jira/browse/HTTPCLIENT-1119

l'implémentation client sous-jacente de Java 7 est capable de la prendre en charge et expose la fonctionnalité via SSLSocketImpl # setHost (appelée par Sun.net.www.protocol.https.HttpsClient

sur l'utilisation de Java 7

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

jusqu'à ce que HTTPCLIENT-1119 soit corrigé

11
cmbntr

Voici comment je l'ai fait dans httpclient v4.3 + d'org.Apache.httpcomponents 

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;
}

Et voici comment j’ai créé le 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();
5
shreyas

avec un correctif court comme décrit dans: TLS avec SNI dans les clients Java Il est possible d’ajouter la prise en charge du serveur SNI à JDK 7 et de l’utiliser conjointement avec X509ExtendedKeyManager.

1
SkateScout

Ce qui a fonctionné pour moi, c’est de configurer correctement la ServerName dans la configuration d’Apache:

/etc/Apache2/sites-avaible/default

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

Comme indiqué dans https://stackoverflow.com/a/8058839/2088282 .

1
Giovanni Silva

Il semble que ce problème soit résolu dans Java 7 .

0
a.drew.b