web-dev-qa-db-fra.com

Ignorer les erreurs de certificat SSL avec Java

Apache Http Client. Vous pouvez voir le code correspondant ici :

String url = "https://path/to/url/service";
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);

// Test whether to ignore cert errors
if (ignoreCertErrors){
  TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager(){
      public X509Certificate[] getAcceptedIssuers(){ return null; }
      public void checkClientTrusted(X509Certificate[] certs, String authType) {}
      public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    }
  };

  try {
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
  } catch (Exception e){
    e.printStackTrace();
  }
}

try {

  // Execute the method (Post) and set the results to the responseBodyAsString()
  int statusCode = client.executeMethod(method);
  resultsBody = method.getResponseBodyAsString();

} catch (HttpException e){
  e.printStackTrace();
} catch (IOException e){
  e.printStackTrace();
} finally {
  method.releaseConnection();
}

C’est la méthode que tout le monde dit d’ignorer les erreurs de certificat SSL (elle ne sert que pour le transfert, elle ne sera pas utilisée en production). Cependant, je reçois toujours l'exception/stacktrace suivante:

javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: PKIX path building unable to find valid certification path to requested target

Tous les conseils seraient géniaux. Si je fais le mauvais TrustManager, ou si je devrais exécuter la méthode HTTP Post différemment, d'une façon ou d'une autre.

Merci!

8
andrewpthorp

Premièrement, évitez les _ ignorer erreurs de certificat. Traiter avec eux à la place. Ignorer les erreurs de certificat ouvre la connexion aux attaques potentielles de MITM. C'est comme si vous éteigniez la sonnerie de votre détecteur de fumée, car parfois il fait du bruit ...

Bien sûr, il est tentant de dire que c'est uniquement pour le code de test, il ne se retrouvera pas dans la production, mais nous savons tous ce qui se passe lorsque la date limite approche: le code ne montre aucune erreur lorsqu'il est testé -> nous pouvons l'expédier. tel quel. Vous devez configurer une autorité de certification test si vous en avez besoin. Ce n'est pas très difficile à créer, et le processus global n'est certainement pas plus difficile que d'introduire un code personnalisé pour le développement et de le supprimer en production.

Vous utilisez visiblement Apache Http Client:

HttpClient client = new HttpClient();
int statusCode = client.executeMethod(method);

Pourtant, vous initialisez le javax.net.ssl.HttpsURLConnection avec la SSLContext que vous avez créée:

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

Ceci est complètement indépendant des paramètres du client Apache Http.

A la place, vous devez configurer la variable SSLContext pour la bibliothèque du client Apache Http, comme décrit dans cette réponse . Si vous utilisez Apache Http Client 3.x, vous devez configurer votre propre SecureProtocolSocketFactory pour utiliser cette SSLContext (voir exemples ici ). Cependant, cela vaut la peine de passer à Apache Http Client 4.x, qui supporte directement SSLContext.

Vous pouvez également utiliser la réponse de Pascal pour importer le certificat correctement. Encore une fois, si vous suivez la réponse acceptée (par Kevin) à cette question, vous allez effectivement ignorer l'erreur mais cela rendra la connexion vulnérable aux attaques MITM.

12
Bruno

HttpClient 4.3, c'est facile, 

     HttpClientBuilder cb = HttpClientBuilder.create();
     SSLContextBuilder sslcb = new SSLContextBuilder();
     sslcb.loadTrustMaterial(KeyStore.getInstance(KeyStore.getDefaultType()), new TrustSelfSignedStrategy());
     cb.setSslcontext(sslcb.build());
     CloseableHttpClient httpclient = cb.build();

cela devrait résoudre votre problème

1
eddy_sby2000

Ignorer des certificats a des effets néfastes, car le même code peut évoluer dans un environnement de production et causer des dégâts. 

L'exemple ci-dessous est avec Jersey Rest Client

private static final com.Sun.jersey.api.client.Client client = com.Sun.jersey.api.client.Client.create(configureClient());
final com.Sun.jersey.api.client.WebResource webResource = client.resource("url");
try {
    com.Sun.jersey.api.client.ClientResponse response = webResource.type(MediaType.APPLICATION_JSON_TYPE)
                            .accept(MediaType.APPLICATION_JSON_TYPE)
                            .get(com.Sun.jersey.api.client.ClientResponse.class);
}catch(com.Sun.jersey.api.client.ClientHandlerException che){
    che.printStackTrace();  
}

Et ignorer les certificats peut être comme ci-dessous:

public static ClientConfig configureClient() {
    TrustManager[ ] certs = new TrustManager[ ] {
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
            }
    };
    SSLContext ctx = null;
    try {
        ctx = SSLContext.getInstance("SSL");
        ctx.init(null, certs, new SecureRandom());
    } catch (Java.security.GeneralSecurityException ex) {
    }
    HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());

    ClientConfig config = new DefaultClientConfig();
    try {
        config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(
                new HostnameVerifier() {
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                },
                ctx
        ));
    } catch(Exception e) {
    }

    return config;
}
0
Amit Kaneria

Si vous voulez vraiment ignorer tout ce qui a fonctionné pour moi:

SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
}).build();
HostnameVerifier hnv = new NoopHostnameVerifier();      
SSLConnectionSocketFactory sslcf = new SSLConnectionSocketFactory(sslContext, hnv);     
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslcf).build()
0
Kyle