So ignorieren Sie SSL-Zertifikatfehler in Apache HttpClient 4.0

125

Wie umgehe ich ungültige SSL-Zertifikatfehler mit Apache HttpClient 4.0?

Viet
quelle
12
Es sollte beachtet werden, dass die Antworten auf diese Frage nicht mehr als das tun, was gefragt wird: Sie können den Fehler ignorieren, aber das zugrunde liegende Problem nicht beheben (ein bisschen wie das Entfernen der Batterien aus einem Rauchmelder, anstatt das Feuer zu löschen ). Zertifikate dienen dazu, die Sicherheit der SSL / TLS-Verbindung zu gewährleisten. Das Ignorieren dieser Fehler führt zu einer Sicherheitsanfälligkeit für MITM-Angriffe. Verwenden Sie Testzertifikate, anstatt den Fehler zu ignorieren.
Bruno
46
"wie das Entfernen der Batterien aus einem Rauchmelder" Sie könnten anderen Entwicklern den Vorteil des Zweifels geben und davon ausgehen, dass sie wissen, was sie tun. Vielleicht liegt die Motivation für diese Frage in lokalen Tests, und das OP möchte einen schnellen Test durchführen, ohne die schrecklichen Mengen an Java-Boilerplate zu durchlaufen, die zum Einrichten selbst einer einfachen SSL-Umgebung erforderlich sind. Vielleicht könnte jemand die Frage einfach beantworten, ohne in einen Vortrag "Heiliger als du" zu gehen.
Mike
Das heißt, in unserem unternehmensinternen JIRA-Server gibt es ein "Windows-Sicherheitsrichtlinien-basiertes Zertifikat", das auf Windows-Computern gültig ist, die in der Domäne enthalten sind, und auf anderen Computern nicht gültig ist. Ich kann diese Richtlinie nicht steuern und möchte trotzdem die JIRA REST-API aufrufen.
odiszapc
1
@Bruno Die Unfähigkeit, Rauchmelder für einen Zeitraum von 30 bis 60 Minuten zu deaktivieren, während ich mich mit einem kleinen Küchenbrand befasse, zeigt einen wahnsinnigen Mangel an Einsicht in die Verwendungsmuster eines gesetzlichen Beamten an einem Punkt, an dem ich mich als kriminell fühle. Die Tatsache, dass es ein Konzept zum "Entfernen von Batterien aus einem Rauchmelder" gibt, beweist dies. Ich bin ungefähr genauso verärgert darüber, dass ich Zertifikate für einen einfachen Test benötigen muss, von dem ich weiß, dass er keine Auswirkungen auf die Sicherheit hat. Die Existenz dieser Frage beweist dies.
Bill K

Antworten:

84

Sie müssen einen SSLContext mit Ihrem eigenen TrustManager erstellen und unter Verwendung dieses Kontexts ein HTTPS-Schema erstellen. Hier ist der Code,

SSLContext sslContext = SSLContext.getInstance("SSL");

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);

// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);
ZZ Coder
quelle
1
Angenommen, ich möchte kein gültiges SSL-Zertifikat für meine Site kaufen und es nur verwenden. Dieser Code kann helfen. Wie kommt es, dass ich keinen Teil sehe, in dem eine URL benötigt wird oder eine Ausnahmebehandlung erforderlich ist?
Viet
19
Hmm, es sagt mir, dass 'new SSLSocketFactory (ssslCont)' einen KeyStore erwartet, keinen SSLContext. Vermisse ich etwas
MSpeed
2
Ich erhalte die Fehlermeldung, dass ein X509TrustManager nicht in einen TrustManager umgewandelt werden kann.
MW.
2
Stellen Sie sicher, dass Sie die richtigen Pakete importieren, dh aus org.apache.http.
Direktor
2
Weiß jemand, wie man das alles zusammenwirft HttpClientBuilder?
Ali
112

Alle anderen Antworten waren entweder veraltet oder funktionierten für HttpClient 4.3 nicht.

Hier ist eine Möglichkeit, alle Hostnamen beim Erstellen eines http-Clients zuzulassen.

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE)
    .build();

Wenn Sie Version 4.4 oder höher verwenden, sieht der aktualisierte Aufruf folgendermaßen aus:

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .build();
erversteeg
quelle
Vielen Dank für die Antwort. Ich möchte wissen, aus welchem ​​Paket HttpsClients stammt, wie ich es in der Android-Kompilierung verwende ("org.apache.httpcomponents: httpclient: 4.3.4"), aber diese Klasse wird nicht angezeigt.
Juan Saravia
1
Das Paket lautet org.apache.http.impl.client.HttpClients.
Erversteeg
14
Dies funktioniert um eine Nichtübereinstimmung des Hostnamens (ich nehme an), aber es scheint nicht zu funktionieren, wenn das Zertifikat nicht von einer vertrauenswürdigen Behörde signiert ist.
Twm
1
@twm Aus diesem Grund heißt es, dass "alle Hostnamen zulässig sind". Vertrauensprobleme erfordern eine andere Konfiguration.
Eis
1
@eis, ich habe darauf hingewiesen, dass diese Antwort in bestimmten Fällen die ursprüngliche Frage anspricht, in anderen jedoch nicht.
Twm
43

Musste dies nur mit dem neueren HttpClient 4.5 machen und es scheint, als hätten sie seit 4.4 ein paar Dinge veraltet. Hier ist das Snippet, das für mich funktioniert und die neueste API verwendet:

final SSLContext sslContext = new SSLContextBuilder()
        .loadTrustMaterial(null, (x509CertChain, authType) -> true)
        .build();

return HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .setConnectionManager(
                new PoolingHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.INSTANCE)
                                .register("https", new SSLConnectionSocketFactory(sslContext,
                                        NoopHostnameVerifier.INSTANCE))
                                .build()
                ))
        .build();
Z4-
quelle
Arbeitete für mich auch für httpclient 4.5.2
Vikas Ranjan
Dieser ist für HttpClient 4.5 auf dem neuesten Stand
Sie sind fantastisch
31

Nur zur Veranschaulichung: Es gibt eine viel einfachere Möglichkeit, dies mit HttpClient 4.1 zu erreichen

    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

        public boolean isTrusted(
                final X509Certificate[] chain, String authType) throws CertificateException {
            // Oh, I am easy...
            return true;
        }

    });
ok2c
quelle
1
Fehlt Ihnen in diesem Beispiel Code? Vielleicht ein Anruf bei httpClient.set ...?
Grau
6
httpclient.getConnectionManager (). getSchemeRegistry (). register (neues Schema ("https", 443, sslsf));
Ben Flynn
8
SSLSocketFactory ist in HttpClient 4.3
Toilal
1
Wenn Sie Java 8 verwenden, können Sie sogarnew SSLSocketFactory((chain, authType) -> true);
jlb
28

Apache HttpClient 4.5.5

HttpClient httpClient = HttpClients
            .custom()
            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
            .build();

Es wurde keine veraltete API verwendet.

Einfacher überprüfbarer Testfall:

package org.apache.http.client.test;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class ApacheHttpClientTest {

    private HttpClient httpClient;

    @Before
    public void initClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        httpClient = HttpClients
                .custom()
                .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }

    @Test
    public void apacheHttpClient455Test() throws IOException {
        executeRequestAndVerifyStatusIsOk("https://expired.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://wrong.host.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://self-signed.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://untrusted-root.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://revoked.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://pinning-test.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://sha1-intermediate.badssl.com");
    }

    private void executeRequestAndVerifyStatusIsOk(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        assert statusCode == 200;
    }
}
Mikhail Kholodkov
quelle
Danke dir! Ändern Sie einfach TrustAllStrategy.INSTANCEmit TrustSelfSignedStrategy.INSTANCEin dieser Antwort.
Percy Vega
Das hat bei mir nicht funktioniert. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen: sun.security. provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden werden
ggb667
26

Für die Aufzeichnung, getestet mit httpclient 4.3.6 und kompatibel mit Executor of Fluent API:

CloseableHttpClient httpClient = HttpClients.custom().
                    setHostnameVerifier(new AllowAllHostnameVerifier()).
                    setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
                    {
                        public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
                        {
                            return true;
                        }
                    }).build()).build();
STM
quelle
3
Ab HttpClient 4.4 müssen Sie dies tun - und müssen möglicherweise auch eine erstellen , die dies SSLConnectionSocketFactoryverwendet SSLContext, und dies in a definieren Registry<ConnectionSocketFactory>, wenn Sie eine erstellen möchten PoolingHttpClientConnectionManager. Die anderen Antworten sind beliebter, funktionieren aber bei HttpClient 4.4 nicht.
Thomas W
1
Funktioniert genau so mit httpclient-4.3.5.jar.
Harald
18

Für Apache HttpClient 4.4:

HttpClientBuilder b = HttpClientBuilder.create();

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        return true;
    }
}).build();
b.setSslcontext( sslContext);

// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", sslSocketFactory)
        .build();

// allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);

HttpClient client = b.build();

Dies wird aus unserer tatsächlichen Arbeitsimplementierung extrahiert.

Die anderen Antworten sind beliebt, aber für HttpClient 4.4 funktionieren sie nicht. Ich habe Stunden damit verbracht, Möglichkeiten auszuprobieren und auszuschöpfen, aber es scheint bei 4.4 extrem große Änderungen und Verschiebungen der API gegeben zu haben.

Siehe auch eine etwas ausführlichere Erklärung unter: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Hoffentlich hilft das!

Thomas W.
quelle
2
Ich war das SSLContext-Bit, das ich brauchte. So sehr verpflichtet.
Hammelfleisch
14

Wenn Sie nur ungültige Hostnamenfehler beseitigen möchten, können Sie einfach Folgendes tun:

HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
    .getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
David Tinker
quelle
8
Die Methode sf.setHostnameVerifier ist ab 4.1 veraltet. Die Alternative besteht darin, einen der Konstruktoren zu verwenden. Zum Beispiel:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Kaliatech
Dies war sehr nützlich, wenn ich mich mit Legacy-Code befassen musste.
DuncanSungWKim
9

Wir verwenden HTTPClient 4.3.5 und haben versucht, dass fast alle Lösungen im Stackoverflow existieren, aber nichts. Nachdem wir das Problem überlegt und herausgefunden haben, kommen wir zu dem folgenden Code, der perfekt funktioniert. Fügen Sie ihn einfach hinzu, bevor Sie eine HttpClient-Instanz erstellen.

eine Methode zum Aufrufen bei Post-Anfragen ....

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

    HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
    HttpPost postRequest = new HttpPost(url);

Setzen Sie Ihre Anfrage in der normalen Form fort

Hamed MP
quelle
7

Mit fließendem 4.5.2 musste ich die folgenden Änderungen vornehmen, damit es funktioniert.

try {
    TrustManager[] trustAllCerts = new TrustManager[] {
       new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
    public void checkClientTrusted(X509Certificate[] certs, String authType) {  }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {  }
    }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSslcontext(sc).build();

    String output = Executor.newInstance(httpClient).execute(Request.Get("https://127.0.0.1:3000/something")
                                      .connectTimeout(1000)
                                      .socketTimeout(1000)).returnContent().asString();
    } catch (Exception e) {
    }
Talespin_Kit
quelle
1
Dies ist die einzige Lösung, die für mich funktioniert hat. Ich habe die oben genannten Lösungen für 4.3 und 4.4 ausprobiert, bevor ich auf 4.5 aktualisiert und dies versucht habe.
Dirkoneill
6

So habe ich es gemacht -

  1. Erstellen Sie meine eigene MockSSLSocketFactory (Klasse unten angefügt)
  2. Verwenden Sie diese Option, um DefaultHttpClient zu initialisieren. Proxy-Einstellungen müssen angegeben werden, wenn ein Proxy verwendet wird.

DefaultHTTPClient wird initialisiert -

SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme("https", 443, new MockSSLSocketFactory()));
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);

    DefaultHttpClient httpclient = new DefaultHttpClient(cm);

Mock SSL Factory -

public class MockSSLSocketFactory extends SSLSocketFactory {

public MockSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(trustStrategy, hostnameVerifier);
}

private static final X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {
    @Override
    public void verify(String host, SSLSocket ssl) throws IOException {
        // Do nothing
    }

    @Override
    public void verify(String host, X509Certificate cert) throws SSLException {
        //Do nothing
    }

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
        //Do nothing
    }

    @Override
    public boolean verify(String s, SSLSession sslSession) {
        return true; 
    }
};

private static final TrustStrategy trustStrategy = new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
};
}

Wenn Sie sich hinter einem Proxy befinden, müssen Sie dies tun -

HttpParams params = new BasicHttpParams();
    params.setParameter(AuthPNames.PROXY_AUTH_PREF, getClientAuthPrefs());

DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);

httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(proxyHost, proxyPort),
                        new UsernamePasswordCredentials(proxyUser, proxyPass));
Swaroop Rath
quelle
Es wäre hilfreich, wenn Sie die Importe in die Zukunft einbeziehen würden. Es gibt zwei verschiedene Klassen.
AndroidDev
4

In Erweiterung der Antwort von ZZ Coder ist es hilfreich, den Hostnamenverifier zu überschreiben.

// ...
SSLSocketFactory sf = new SSLSocketFactory (sslContext);
sf.setHostnameVerifier(new X509HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }

    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
    }

    public void verify(String host, X509Certificate cert) throws SSLException {
    }

    public void verify(String host, SSLSocket ssl) throws IOException {
    }
});
// ...
eldur
quelle
Sie können das gleiche erreichen, indem Sie einfach tunsf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer
7
Der sf.setHostnameVerifier ist ab 4.1 veraltet. Die Alternative besteht darin, einen der Konstruktoren zu verwenden. Zum Beispiel:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Kaliatech
4
        DefaultHttpClient httpclient = new DefaultHttpClient();

    SSLContext sslContext;
    try {
        sslContext = SSLContext.getInstance("SSL");

        // set up a TrustManager that trusts everything
        try {
            sslContext.init(null,
                    new TrustManager[] { new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            log.debug("getAcceptedIssuers =============");
                            return null;
                        }

                        public void checkClientTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkClientTrusted =============");
                        }

                        public void checkServerTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkServerTrusted =============");
                        }
                    } }, new SecureRandom());
        } catch (KeyManagementException e) {
        }
         SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
         ClientConnectionManager ccm = this.httpclient.getConnectionManager();
         SchemeRegistry sr = ccm.getSchemeRegistry();
         sr.register(new Scheme("https", 443, ssf));            
    } catch (Exception e) {
        log.error(e.getMessage(),e);
    }
kleiner Tiger
quelle
4

Um alle Zertifikate in HttpClient 4.4.x zu akzeptieren, können Sie beim Erstellen des httpClient den folgenden Liner verwenden:

httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build()).build();
Kühl
quelle
Ich erhalte Folgendes: Auslöser: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Keine alternativen Betreffnamen vorhanden?
Wie erlaube ich Verbindungen zu SSL-Sites ohne Zertifikate in der HttpClient-API oder in der RestClient-API?
4

Getestet mit HttpClient 4.5.5 mit Fluent API

final SSLContext sslContext = new SSLContextBuilder()
    .loadTrustMaterial(null, (x509CertChain, authType) -> true).build();

CloseableHttpClient httpClient = HttpClients.custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .setSSLContext(sslContext).build();

String result = Executor.newInstance(httpClient)
    .execute(Request.Get("https://localhost:8080/someapi")
    .connectTimeout(1000).socketTimeout(1000))
    .returnContent().asString();
Lachesis
quelle
3

Der folgende Code funktioniert mit 4.5.5

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

class HttpsSSLClient {


    public static CloseableHttpClient createSSLInsecureClient() {
        SSLContext sslcontext = createSSLContext();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new HostnameVerifier() {

            @Override
            public boolean verify(String paramString, SSLSession paramSSLSession) {
                return true;
            }
        });
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        return httpclient;
    }


    private static SSLContext createSSLContext() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[] {new TrustAnyTrustManager()}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslcontext;
    }


    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }

}
public class TestMe {


    public static void main(String[] args) throws IOException {
        CloseableHttpClient client = HttpsSSLClient.createSSLInsecureClient();

        CloseableHttpResponse res = client.execute(new HttpGet("https://wrong.host.badssl.com/"));
        System.out.println(EntityUtils.toString(res.getEntity()));
    }
}

Ausgabe von Code ist

Code

Ausgabe im Browser ist

Schlechtes SSL

Der verwendete Pom ist unten

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tarun</groupId>
    <artifactId>testing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

</dependencies>
</project>
Tarun Lalwani
quelle
Vielen Dank für die aktualisierte Antwort. Ich habe dem neuen Mann das Kopfgeld für "Willkommen" verliehen, aber ich wollte nur aktualisierte Antworten für alle!
1
@ Feelingunwelcome, sicher. Ich habe ihn auch positiv bewertet :-)
Tarun Lalwani
2

eine voll funktionsfähige Version für Apache HttpClient 4.1.3 (basierend auf dem obigen Code von oleg, aber es wurde immer noch ein allow_all_hostname_verifier auf meinem System benötigt):

private static HttpClient trustEveryoneSslHttpClient() {
    try {
        SchemeRegistry registry = new SchemeRegistry();

        SSLSocketFactory socketFactory = new SSLSocketFactory(new TrustStrategy() {

            public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
                // Oh, I am easy...
                return true;
            }

        }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        registry.register(new Scheme("https", 443, socketFactory));
        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
        DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
        return client;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

Beachten Sie, dass ich alle Ausnahmen erneut auslöse, da ich wirklich nicht viel tun kann, wenn dies in einem realen System fehlschlägt!

Korny
quelle
2

Wenn Sie die fließende API verwenden , müssen Sie sie über Folgendes einrichten Executor:

Executor.unregisterScheme("https");
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext,
                                  SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Executor.registerScheme(new Scheme("https", 443, sslSocketFactory));

... wo sslContextwird der SSLContext erstellt, wie in der Antwort des ZZ- Codierers gezeigt .

Danach können Sie Ihre http-Anfragen wie folgt ausführen:

String responseAsString = Request.Get("https://192.168.1.0/whatever.json")
                         .execute().getContent().asString();

Hinweis: getestet mit HttpClient 4.2

Elias Dorneles
quelle
Leider veraltet in 4.3: "Veraltet. (4.3) nicht verwenden."
STM
2

Getestet mit 4.3.3

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class AccessProtectedResource {

public static void main(String[] args) throws Exception {

    // Trust all certs
    SSLContext sslcontext = buildSSLContext();

    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://yoururl");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            for (Header header : response.getAllHeaders()) {
                System.out.println(header);
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

private static SSLContext buildSSLContext()
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException {
    SSLContext sslcontext = SSLContexts.custom()
            .setSecureRandom(new SecureRandom())
            .loadTrustMaterial(null, new TrustStrategy() {

                public boolean isTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    return true;
                }
            })
            .build();
    return sslcontext;
}

}}

craftsmannadeem
quelle
Wie setze ich Werte in Headern, wenn ich das tun wollte?
2

Getestet am 4.5.4:

            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build();

            CloseableHttpClient httpClient = HttpClients
                    .custom()
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setSSLContext(sslContext)
                    .build();
Jacky
quelle
0

Wenn dieses Problem bei der Verwendung von AmazonS3Client aufgetreten ist, in das Apache HttpClient 4.1 eingebettet ist, müssen Sie lediglich eine solche Systemeigenschaft definieren, damit die SSL-Zertifizierungsprüfung gelockert wird:

-Dcom.amazonaws.sdk.disableCertChecking = true

Unfug schaffte es

Mike Slinn
quelle
0

fwiw, ein Beispiel für die Verwendung der "RestEasy" -Implementierung von JAX-RS 2.x zum Erstellen eines speziellen "Trust All" -Clients ...

    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.security.GeneralSecurityException;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.Arrays;
    import javax.ejb.Stateless;
    import javax.net.ssl.SSLContext;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.HttpClientConnectionManager;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.jboss.resteasy.client.jaxrs.ResteasyClient;
    import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
    import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
    import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
    import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.ssl.SSLContexts;

    @Stateless
    @Path("/postservice")
    public class PostService {

        private static final Logger LOG = LogManager.getLogger("PostService");

        public PostService() {
        }

        @GET
        @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
        public PostRespDTO get() throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException, IOException, GeneralSecurityException {

            //...object passed to the POST method...
            PostDTO requestObject = new PostDTO();
            requestObject.setEntryAList(new ArrayList<>(Arrays.asList("ITEM0000A", "ITEM0000B", "ITEM0000C")));
            requestObject.setEntryBList(new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));

            //...build special "trust all" client to call POST method...
            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(createTrustAllClient());

            ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
            ResteasyWebTarget target = client.target("https://localhost:7002/postRespWS").path("postrespservice");
            Response response = target.request().accept(MediaType.APPLICATION_JSON).post(Entity.entity(requestObject, MediaType.APPLICATION_JSON));

            //...object returned from the POST method...
            PostRespDTO responseObject = response.readEntity(PostRespDTO.class);

            response.close();

            return responseObject;
        }


        //...get special "trust all" client...
        private static CloseableHttpClient createTrustAllClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, TRUSTALLCERTS).useProtocol("TLS").build();
            HttpClientBuilder builder = HttpClientBuilder.create();
            NoopHostnameVerifier noop = new NoopHostnameVerifier();
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, noop);
            builder.setSSLSocketFactory(sslConnectionSocketFactory);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
            HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
            builder.setConnectionManager(ccm);

            return builder.build();
        }


        private static final TrustStrategy TRUSTALLCERTS = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
                return true;
            }
        };
    }

verwandte Maven-Abhängigkeiten

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>jaxrs-api</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency> 
sairn
quelle
-1

Wenn Sie Apache httpClient 4.5.x verwenden, versuchen Sie Folgendes :

public static void main(String... args)  {

    try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
        HttpGet httpget = new HttpGet("https://example.com");
        System.out.println("Executing request " + httpget.getRequestLine());

        httpclient.execute(httpget);
        System.out.println("----------------------------------------");
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

    // use the TrustSelfSignedStrategy to allow Self Signed Certificates
    SSLContext sslContext = SSLContextBuilder
            .create()
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    // we can optionally disable hostname verification. 
    // if you don't want to further weaken the security, you don't have to include this.
    HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

    // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
    // and allow all hosts verifier.
    SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

    // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
    return HttpClients
            .custom()
            .setSSLSocketFactory(connectionFactory)
            .build();
}
Brijesh Patel
quelle