web-dev-qa-db-fra.com

Ignorer les certificats auto-signés dans Apache HTTPClient 4.5

J'essaie d'accepter tous les certificats et/ou d'accepter les certificats auto-signés en utilisant Apache HTTPClient version 4.5 (lien tutoriel ici )

J'ai cherché des solutions à ce problème à partir d'un tas de messages sur SO. Jusqu'à présent, aucun d'entre eux n'a fonctionné.

Je reçois toujours cette erreur: Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote Host closed connection during handshake

Apache Docs:

Questions StackOverflow connexes - Voici quelques liens des solutions que j'ai essayées:

Notez que dans tous ces exemples, je transmets également un magasin de cookies et un fournisseur d'informations d'identification de proxy que j'ai défini précédemment. Ceux-ci fonctionnent, j'essaie simplement d'ajouter le support SSL.

Essayez # 1

Créer mon propre contexte SSL avec SSLContextBuilder et faire confiance à toutes les stratégies auto-signées avec TrustSelfSignedStrategy.

SSLContextBuilder sshbuilder = new SSLContextBuilder();
sshbuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sshbuilder.build());

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

[~ # ~] résultat [~ # ~] : n'a pas fonctionné. Eu Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote Host closed connection during handshake

Essayez # 2

Comme ci-dessus, mais ajoutez un PoolingHttpClientConnectionManager

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(2000);//max connection

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .setConnectionManager(cm)
    .build();

[~ # ~] résultat [~ # ~] : n'a pas fonctionné. Eu Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote Host closed connection during handshake

Essayez # 3

Acceptez simplement TOUS les certificats en remplaçant TrustStrategy (ce n'est pas recommandé)

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
});
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

[~ # ~] résultat [~ # ~] : n'a pas fonctionné. Eu Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote Host closed connection during handshake

Essayez # 4

J'ai trouvé quelque chose d'utile de cette réponse :

Depuis la version 4.5, HttpClient désactive la version du protocole SSLv3 par défaut

Voici la solution qu'il a donnée:

SSLContext sslcontext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
        sslcontext, new String[] { "TLSv1", "SSLv3" }, null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.INSTANCE)
        .register("https", sslConnectionSocketFactory)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslConnectionSocketFactory)
    .setConnectionManager(cm)
    .build();

[~ # ~] résultat [~ # ~] : n'a pas fonctionné. Eu Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote Host closed connection during handshake

11
Katie

L'une des approches ci-dessus devrait fonctionner en cas de certificats auto-signés, mais la chose étrange est que vous obtenez la même exception dans toutes les approches.

Je pense que lors de l'établissement de la session SSL ou du protocole de négociation n'est accepté ni par le client ni par le serveur.

La meilleure solution ici est de déboguer l'application.

Dans le cas de Tomcat, ajoutez - Djavax.net.debug = all dans les fichiers setenv.sh ou setenv.bat, puis redémarrez le serveur.

Ou vous pouvez suivre ce tutoriel .

L'OP avait juste besoin de changer le port lors de la connexion à SSL:

//For HTTPS
HttpHost httpstarget = new HttpHost("mysite.com", 443, "https");

//For HTTP
HttpHost httptarget = new HttpHost("mysite.com", 80, "http");
3
Azim

J'utilise Apache HttpClient 4.5.3 et aucune des solutions ci-dessus n'a aidé. J'ai toujours l'erreur

Échec de la création du chemin PKIX

.

J'ai trouvé la solution dans http://www.baeldung.com/httpclient-ssl

Voici mon code:

try {
    SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null, (certificate, authType) -> true).build();
    httpClient = HttpClients.custom().setSSLContext(sslContext)
            .setSSLHostnameVerifier(new NoopHostnameVerifier())
            .build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
    e.printStackTrace();
}
10
Martin Pabst

Très souvent, vous devez non seulement prendre en charge les certificats auto-signés, mais également invoquer des demandes multithreads, et donc utiliser un gestionnaire de connexions de mise en commun. Voici comment je le fais:

private CloseableHttpClient newClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    SSLContext context = SSLContexts.custom()
            .loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE)
            .build();

    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE))
            .build();

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

    return HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();
}
6
Yaniv Nahoum
public static HttpClient newClient() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            e.printStackTrace();
        }

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext,
                (s, sslSession) -> true);

        return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
                .build();
    }
2
Oleg Maksymuk