it-swarm.com.de

SSL-Zertifikatfehler mit Java ignorieren

Apache-HTTP-Client. Den entsprechenden Code sehen Sie hier :

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

Dies ist die Methode, die jeder verwenden soll, um SSL-Zertifikatfehler zu ignorieren (dies wird nur für das Staging eingerichtet und wird nicht in der Produktion verwendet). Ich erhalte jedoch immer noch die folgende Ausnahme/Stacktrace:

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

Irgendwelche Tipps wären toll. Wenn ich den TrustManager falsch mache oder die HTTP-Post-Methode auf andere Weise ausführen soll, so oder so.

Vielen Dank!

8
andrewpthorp

Erstens: Nicht Ignorieren Zertifikatfehler. Behandle sie stattdessen. Das Ignorieren von Zertifikatsfehlern öffnet die Verbindung zu potenziellen MITM-Angriffen. Es ist, als würde man den Summer in Ihrem Rauchmelder ausschalten, weil es manchmal ein Geräusch macht ...

Sicher, es ist verlockend zu sagen, dass es nur für Testcode ist, er wird nicht in der Produktion enden, aber wir alle wissen, was passiert, wenn die Frist näher rückt: Der Code zeigt keine Fehler, wenn er getestet wird -> wir können ihn versenden wie es ist. Sie sollten stattdessen eine Testzertifizierungsstelle einrichten, wenn Sie dies benötigen. Es ist nicht sehr schwer zu erstellen, und der Gesamtprozess ist sicherlich nicht schwieriger als die Einführung von benutzerdefiniertem Code für die Entwicklung und das Entfernen in der Produktion.

Sie verwenden den Apache Http Client sichtbar:

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

Sie initialisieren den javax.net.ssl.HttpsURLConnection jedoch mit der von Ihnen erstellten SSLContext:

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

Dies ist völlig unabhängig von den Apache Http Client-Einstellungen.

Stattdessen sollten Sie die Variable SSLContext für die Apache Http Client-Bibliothek wie in diese Antwort beschrieben einrichten. Wenn Sie Apache Http Client 3.x verwenden, müssen Sie Ihre eigene SecureProtocolSocketFactory einrichten, um diese SSLContext zu verwenden (siehe Beispiele hier ). Ein Upgrade auf Apache Http Client 4.x lohnt sich jedoch, da hier SSLContext direkt unterstützt wird.

Sie können auch die Antwort von Pascal verwenden, um das Zertifikat korrekt zu importieren. Wenn Sie der akzeptierten Antwort (von Kevin) auf diese Frage folgen, werden Sie den Fehler zwar ignorieren, dies macht jedoch die Verbindung für MITM-Angriffe anfällig.

12
Bruno

HttpClient 4.3, es ist einfach, 

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

das sollte dein Problem beheben

1
eddy_sby2000

Das Ignorieren von Zertifikaten hat seinen eigenen Schaden, da derselbe Code sich in der Produktionsumgebung bewegen und Verwüstungen verursachen kann. 

Das folgende Beispiel ist mit 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();  
}

Das Ignorieren von Zertifikaten kann wie folgt sein:

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

Wenn Sie wirklich alles ignorieren möchten, hat dies für mich funktioniert:

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