web-dev-qa-db-fra.com

javax.net.ssl.SSLPeerUnverifiedException: le nom d'hôte ne correspond pas à l'objet du certificat fourni par l'homologue

Je suis plusieurs liens sur stackoverflow et j'ai essayé plusieurs solutions, mais aucune d’elles n’a fonctionné pour moi. J'utilise WSO2 API manager version 1.9.1. Je suis confronté à l'erreur suivante:

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'XXXXXXXXX' does not match the certificate subject provided by the peer (CN=localhost, O=WSO2, L=Mountain View, ST=CA, C=US)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.Java:465)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.Java:395)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.Java:353)
    at org.Apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.Java:134)
    at org.Apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.Java:353)
    at org.Apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.Java:380)
    at org.Apache.http.impl.execchain.MainClientExec.execute(MainClientExec.Java:236)
    at org.Apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.Java:184)
    at org.Apache.http.impl.execchain.RetryExec.execute(RetryExec.Java:88)
    at org.Apache.http.impl.execchain.RedirectExec.execute(RedirectExec.Java:110)
    at org.Apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.Java:184)
    at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:82)
    at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:107)
    at com.Java.pushNotifications.WSO2DemoClient.main(WSO2DemoClient.Java:49)

J'ai développé le code Java suivant. S'il vous plaît, aidez-moi à comprendre ce qui ne va pas ici. Je dois me connecter de manière non sécurisée et autoriser les connexions à des sites SSL sans certs.

public static void main(String[] args) throws ClientProtocolException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());

        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().setSSLSocketFactory(sslsf)
                .setConnectionManager(cm).build();

        HttpGet httpGet = new HttpGet("https://XXXXXXXXXX:8243/token");
        CloseableHttpResponse response = httpclient.execute(httpGet);

        String json =" {\"data\":\"grant_type=password&username=test&password=test123\"}";

        try {
            HttpPost httpost = new HttpPost(url);
            httpost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            httpost.setHeader("Authorization", "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

            httpost.setEntity(new StringEntity(json));

            HttpResponse httpResponse = httpclient.execute(httpost);

            System.out.println(httpResponse.getStatusLine());
        }
        finally {
            response.close();
        }

        String responseString1 = new BasicResponseHandler().handleResponse(response);
        System.out.println("Response : "+responseString1);
    }
23
user5268786

J'ai passé une heure à essayer de résoudre le même problème. Voici ce que je viens avec:

final SSLConnectionSocketFactory sslsf;
try {
    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault(),
            NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
}

final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();

final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .setConnectionManager(cm)
        .build();

Espérons que cela fonctionne et n’utilise aucun code obsolète (httpclient 4.4.1).

41
antonpp

Remplacez ceci

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
            .setConnectionManager(cm).build();

avec

CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .setConnectionManager(cm)
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            .build();

Si le certificat n'est pas signé (même pas auto-signé), alors vous pouvez le faire

import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;

public class TrustAllStrategy implements TrustStrategy {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
}

Ensuite

builder.loadTrustMaterial(new TrustAllStrategy());

EDIT: ceci

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, //for you this is builder.build()
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
);
15
EpicPandaForce

Merci à toutes les solutions. J'essaie toutes les solutions disponibles en ligne depuis 1,5 jours maintenant et finalement cela a fonctionné maintenant. Voici le code de travail

 SSLContextBuilder builder = new SSLContextBuilder();
 builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
 Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new PlainConnectionSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();

 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
 cm.setMaxTotal(100);
 CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .setConnectionManager(cm)
            .build();
 HttpPost httpPost = new HttpPost(url);
 httpPost.setEntity(postEntity);
 httpPost.expectContinue();
 CloseableHttpResponse response = httpclient.execute(httpPost);
10
AJC

Voici ce que je suis venu avec:

 SSLContextBuilder sslcontext = new SSLContextBuilder();
 sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
      .build();
5
Dudi

Après avoir essayé la plupart des solutions suggérées sur cette page et d'autres discussions relatives à stackoverflow, j'ai constaté que la réponse d'AJC ci-dessus fonctionne avec Apache httpclient version 4.5.

Motif: lors de la création de SSLConnectionSocketFactory si le HostVerifier n'est pas spécifié dans le constructeur, il n'est pas défini et le DefaultHostVerifier est utilisé. La ligne 3 de la solution d'AJC fait donc la différence.

(Au moins c'est le comportement dans Apache httpclient 4.5.3)

3
Ashutosh