Akzeptieren Sie das selbstsignierte SSL-Zertifikat des Servers im Java-Client

215

Es sieht aus wie eine Standardfrage, aber ich konnte nirgendwo klare Anweisungen finden.

Ich habe Java-Code, der versucht, eine Verbindung zu einem Server mit wahrscheinlich selbstsigniertem (oder abgelaufenem) Zertifikat herzustellen. Der Code meldet den folgenden Fehler:

[HttpMethodDirector] I/O exception (javax.net.ssl.SSLHandshakeException) caught 
when processing request: sun.security.validator.ValidatorException: PKIX path 
building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target

So wie ich es verstehe, muss ich Keytool verwenden und Java mitteilen, dass es in Ordnung ist, diese Verbindung zuzulassen.

Alle Anweisungen zur Behebung dieses Problems setzen voraus, dass ich mit Keytool voll vertraut bin, wie z

Generieren Sie einen privaten Schlüssel für den Server und importieren Sie ihn in den Keystore

Gibt es jemanden, der detaillierte Anweisungen veröffentlichen könnte?

Ich verwende Unix, daher ist Bash-Skript am besten geeignet.

Ich bin mir nicht sicher, ob es wichtig ist, aber der Code wird in jboss ausgeführt.

Nikita Rybak
quelle
2
Siehe Wie akzeptiere ich ein selbstsigniertes Zertifikat mit einer Java HttpsURLConnection? . Natürlich wäre es besser, wenn Sie die Site dazu bringen könnten, ein gültiges Zertifikat zu verwenden.
Matthew Flaschen
2
Vielen Dank für den Link, ich habe ihn bei der Suche nicht gesehen. Beide Lösungen beinhalten jedoch speziellen Code zum Senden einer Anfrage und ich verwende vorhandenen Code (amazon ws client für Java). Es ist ihre Site, die ich verbinde, und ich kann die Zertifikatprobleme nicht beheben.
Nikita Rybak
2
@MatthewFlaschen - " Natürlich ist es besser, wenn Sie die Site dazu bringen können, ein gültiges Zertifikat zu verwenden ..." - Ein selbstsigniertes Zertifikat ist ein gültiges Zertifikat, wenn der Client ihm vertraut. Viele halten es für einen Sicherheitsmangel, dem CA / Browser-Kartell Vertrauen zu verleihen.
JWW
3
Siehe auch Der gefährlichste Code der Welt: Überprüfen von SSL-Zertifikaten in Nicht-Browser-Software . (Der Link wird bereitgestellt, da Sie anscheinend die Spam-Antworten erhalten, die die Validierung deaktivieren.)
JWW

Antworten:

306

Grundsätzlich haben Sie hier zwei Möglichkeiten: Fügen Sie das selbstsignierte Zertifikat zu Ihrem JVM-Truststore hinzu oder konfigurieren Sie Ihren Client für

Option 1

Exportieren Sie das Zertifikat aus Ihrem Browser und importieren Sie es in Ihren JVM-Truststore (um eine Vertrauenskette aufzubauen):

<JAVA_HOME>\bin\keytool -import -v -trustcacerts
-alias server-alias -file server.cer
-keystore cacerts.jks -keypass changeit
-storepass changeit 

Option 2

Zertifikatvalidierung deaktivieren:

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { 
    new X509TrustManager() {     
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
            return new X509Certificate[0];
        } 
        public void checkClientTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
            } 
        public void checkServerTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    } 
}; 

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL"); 
    sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (GeneralSecurityException e) {
} 
// Now you can access an https URL without having the certificate in the truststore
try { 
    URL url = new URL("https://hostname/index.html"); 
} catch (MalformedURLException e) {
} 

Beachten Sie, dass ich die Option 2 überhaupt nicht empfehle . Durch Deaktivieren des Vertrauensmanagers werden einige Teile von SSL besiegt und Sie sind anfällig für Man-in-the-Middle-Angriffe. Bevorzugen Sie Option 1 oder lassen Sie den Server ein "echtes" Zertifikat verwenden, das von einer bekannten Zertifizierungsstelle signiert wurde.

Pascal Thivent
quelle
7
Nicht nur der MIM-Angriff. Es macht Sie anfällig für die Verbindung mit der falschen Site. Es ist völlig unsicher. Siehe RFC 2246. Ich lehne es ab, diesen TrustManager jederzeit zu veröffentlichen. Es ist nicht einmal richtig für seine eigene Spezifikation.
Marquis von Lorne
10
@EJP Ich empfehle die zweite Option wirklich nicht (ich habe meine Antwort aktualisiert, um es klar zu machen). Wenn Sie es jedoch nicht veröffentlichen, wird nichts gelöst (dies sind öffentliche Informationen), und meiner Meinung nach verdient es keine Ablehnung.
Pascal Thivent
135
@EJP Es ist, indem man Menschen lehrt, dass man sie erzieht, nicht indem man Dinge versteckt. Dinge geheim zu halten oder im Dunkeln zu halten, ist also überhaupt keine Lösung. Dieser Code ist öffentlich, die Java-API ist öffentlich, es ist besser, darüber zu sprechen, als ihn zu ignorieren. Aber ich kann mit dir leben, wenn du nicht zustimmst.
Pascal Thivent
10
Die andere Option - die Sie nicht erwähnen - besteht darin , das Serverzertifikat zu reparieren, indem Sie es entweder selbst reparieren oder die entsprechenden Support-Mitarbeiter anrufen. Single-Host-Zertifikate sind wirklich sehr billig; Mit selbstsignierten Sachen herumzuspielen ist penny-weise Pfund-dumm (dh für diejenigen, die mit dieser englischen Sprache nicht vertraut sind, eine völlig dumme Reihe von Prioritäten, die viel kosten, um fast nichts zu sparen).
Donal Fellows
2
@Rich, 6 Jahre zu spät, aber Sie können das Serverzertifikat auch in Firefox erhalten, indem Sie auf das Schlosssymbol klicken -> Weitere Informationen -> Zertifikat anzeigen -> Registerkarte Details -> Exportieren ... Es ist gut versteckt.
Siddhartha
9

Ich habe dieses Problem an einen Zertifikatanbieter weitergeleitet, der ab sofort nicht mehr zu den standardmäßigen vertrauenswürdigen JVM-Hosts gehört JDK 8u74. Der Anbieter ist www.identrust.com , aber das war nicht die Domain, zu der ich eine Verbindung herstellen wollte. Diese Domain hatte ihr Zertifikat von diesem Anbieter erhalten. Siehe Wird das Cross-Root-Cover der Standardliste im JDK / JRE vertrauen? - Lesen Sie ein paar Einträge. Siehe auch Welche Browser und Betriebssysteme unterstützen Let's Encrypt .

Um eine Verbindung zu der Domain herzustellen, an der ich interessiert war und von der ein Zertifikat ausgestellt wurde, habe identrust.comich die folgenden Schritte ausgeführt. Grundsätzlich musste ich das identrust.com ( DST Root CA X3) -Zertifikat erhalten, um von der JVM als vertrauenswürdig eingestuft zu werden. Ich konnte das mit Apache HttpComponents 4.5 wie folgt machen:

1: Beziehen Sie das Zertifikat von indettrust in den Anweisungen zum Herunterladen der Zertifikatskette . Klicken Sie auf den Link DST Root CA X3 .

2: Speichern Sie die Zeichenfolge in einer Datei mit dem Namen "DST Root CA X3.pem". Stellen Sie sicher, dass Sie die Zeilen "----- BEGIN CERTIFICATE -----" und "----- END CERTIFICATE -----" in die Datei am Anfang und am Ende einfügen.

3: Erstellen Sie eine Java-Keystore-Datei, cacerts.jks, mit dem folgenden Befehl:

keytool -import -v -trustcacerts -alias IdenTrust -keypass yourpassword -file dst_root_ca_x3.pem -keystore cacerts.jks -storepass yourpassword

4: Kopieren Sie den resultierenden Keystore cacerts.jks in das Ressourcenverzeichnis Ihrer Java / (Maven) -Anwendung.

5: Verwenden Sie den folgenden Code, um diese Datei zu laden und an den Apache 4.5 HttpClient anzuhängen. Dadurch wird das Problem für alle Domänen gelöst, für die Zertifikate von indetrust.comutil oracle ausgestellt wurden, die das Zertifikat in den JRE-Standardschlüsselspeicher aufnehmen.

SSLContext sslcontext = SSLContexts.custom()
        .loadTrustMaterial(new File(CalRestClient.class.getResource("/cacerts.jks").getFile()), "yourpasword".toCharArray(),
                new TrustSelfSignedStrategy())
        .build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        sslcontext,
        new String[] { "TLSv1" },
        null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpclient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .build();

Wenn das Projekt erstellt wird, werden die cacerts.jks in den Klassenpfad kopiert und von dort geladen. Ich habe zu diesem Zeitpunkt noch keine Tests mit anderen SSL-Sites durchgeführt, aber wenn der obige Code "Ketten" in diesem Zertifikat enthält, funktionieren sie auch, aber ich weiß es auch nicht.

Referenz: Benutzerdefinierter SSL-Kontext und Wie akzeptiere ich ein selbstsigniertes Zertifikat mit einer Java HttpsURLConnection?

K. Nicholas
quelle
Die Frage bezieht sich auf ein selbstsigniertes Zertifikat. Diese Antwort ist nicht.
Marquis von Lorne
4
Lesen Sie die Frage (und Antwort) etwas genauer durch.
K.Nicholas
9

Apache HttpClient 4.5 unterstützt das Akzeptieren selbstsignierter Zertifikate:

SSLContext sslContext = SSLContexts.custom()
    .loadTrustMaterial(new TrustSelfSignedStrategy())
    .build();
SSLConnectionSocketFactory socketFactory =
    new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> reg =
    RegistryBuilder.<ConnectionSocketFactory>create()
    .register("https", socketFactory)
    .build();
HttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg);        
CloseableHttpClient httpClient = HttpClients.custom()
    .setConnectionManager(cm)
    .build();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse sslResponse = httpClient.execute(httpGet);

Dadurch wird eine SSL-Socket-Factory erstellt, die die verwendet TrustSelfSignedStrategy , es bei einem benutzerdefinierten Verbindungsmanager registriert und dann mit diesem Verbindungsmanager ein HTTP-GET ausführt.

Ich stimme denen zu, die "dies in der Produktion nicht tun" singen, es gibt jedoch Anwendungsfälle für die Annahme selbstsignierter Zertifikate außerhalb der Produktion. Wir verwenden sie in automatisierten Integrationstests, sodass wir SSL (wie in der Produktion) verwenden, auch wenn es nicht auf der Produktionshardware ausgeführt wird.

schick
quelle
6

Anstatt die Standard-Socket-Factory festzulegen (was IMO eine schlechte Sache ist), wirkt sich dies nur auf die aktuelle Verbindung aus und nicht auf jede SSL-Verbindung, die Sie öffnen möchten:

URLConnection connection = url.openConnection();
    // JMD - this is a better way to do it that doesn't override the default SSL factory.
    if (connection instanceof HttpsURLConnection)
    {
        HttpsURLConnection conHttps = (HttpsURLConnection) connection;
        // Set up a Trust all manager
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
        {

            public java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }

            public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
            {
            }

            public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
            {
            }
        } };

        // Get a new SSL context
        SSLContext sc = SSLContext.getInstance("TLSv1.2");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        // Set our connection to use this SSL context, with the "Trust all" manager in place.
        conHttps.setSSLSocketFactory(sc.getSocketFactory());
        // Also force it to trust all hosts
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        // and set the hostname verifier.
        conHttps.setHostnameVerifier(allHostsValid);
    }
InputStream stream = connection.getInputStream();
Jon Daniel
quelle
2
Sie checkServerTrustedimplementieren nicht die erforderliche Logik, um dem Zertifikat tatsächlich zu vertrauen und sicherzustellen, dass nicht vertrauenswürdige Zertifikate abgelehnt werden. Dies könnte eine gute Lektüre sein: Der gefährlichste Code der Welt: Validieren von SSL-Zertifikaten in Nicht-Browser-Software .
JWW
1
Ihre getAcceptedIssuers()Methode entspricht nicht der Spezifikation, und diese "Lösung" bleibt radikal unsicher.
Marquis von Lorne
3

Es gibt eine bessere Alternative zum Vertrauen in alle Zertifikate: Erstellen Sie ein Zertifikat TrustStore, das einem bestimmten Zertifikat spezifisch vertraut, und verwenden Sie dieses, um ein Zertifikat zu erstellen, SSLContextvon dem aus das Zertifikat SSLSocketFactoryfestgelegt werden kann HttpsURLConnection. Hier ist der vollständige Code:

File crtFile = new File("server.crt");
Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
connection.setSSLSocketFactory(sslContext.getSocketFactory());

Alternativ können Sie das KeyStoreZertifikat direkt aus einer Datei laden oder das X.509-Zertifikat von einer vertrauenswürdigen Quelle abrufen.

Beachten Sie, dass mit diesem Code die Zertifikate in cacertsnicht verwendet werden. Diese HttpsURLConnectionPerson vertraut nur diesem bestimmten Zertifikat.

Johannes Brodwall
quelle
1

Vertrauen Sie allen SSL-Zertifikaten: - Sie können SSL umgehen, wenn Sie auf dem Testserver testen möchten. Verwenden Sie diesen Code jedoch nicht für die Produktion.

public static class NukeSSLCerts {
protected static final String TAG = "NukeSSLCerts";

public static void nuke() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] myTrustedAnchors = new X509Certificate[0];  
                    return myTrustedAnchors;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}

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

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception e) { 
    }
}

}}

Rufen Sie diese Funktion in der Funktion onCreate () in Activity oder in Ihrer Anwendungsklasse auf.

NukeSSLCerts.nuke();

Dies kann für Volley in Android verwendet werden.

Ashish Saini
quelle
Ich bin mir nicht ganz sicher, warum Sie abgewählt werden, es sei denn, der Code funktioniert nicht. Vielleicht ist es die Annahme, dass Android irgendwie involviert ist, wenn die ursprüngliche Frage Android nicht markiert hat.
Lo-Tan
1

Die akzeptierte Antwort ist in Ordnung, aber ich möchte etwas hinzufügen, da ich IntelliJ auf dem Mac verwendet habe und es mit der Pfadvariablen nicht zum Laufen bringen konnte JAVA_HOME.

Es stellte sich heraus, dass Java Home beim Ausführen der Anwendung von IntelliJ anders war.

Um genau herauszufinden, wo es sich befindet, können Sie einfach System.getProperty("java.home")die vertrauenswürdigen Zertifikate lesen.

Christopher Schneider
quelle
0

Wenn 'sie' ein selbstsigniertes Zertifikat verwenden, liegt es an ihnen, die erforderlichen Schritte zu unternehmen, um ihren Server nutzbar zu machen. Konkret bedeutet dies, dass Sie das Zertifikat vertrauenswürdig offline bereitstellen. Lassen Sie sie das tun. Anschließend importieren Sie dies mithilfe des Keytools in Ihren Truststore, wie im JSSE-Referenzhandbuch beschrieben. Denken Sie nicht einmal an den unsicheren TrustManager, der hier veröffentlicht wurde.

BEARBEITEN Zum Nutzen der siebzehn (!) Downvoter und zahlreiche Kommentatoren unten, die offensichtlich nicht wirklich gelesen haben, was ich hier geschrieben habe, ist dies keine Jeremiade gegen selbstsignierte Zertifikate. Selbstsignierte Zertifikate sind bei korrekter Implementierung nicht falsch . Aber der richtige Weg , um sie zu implementieren , ist das Zertifikat haben geliefert sicher über einen Offline - Prozess, anstatt über den nicht - autorisierten Kanal sie verwendet wird , werden zu authentifizieren. Sicher ist das offensichtlich? Es ist für jede sicherheitsbewusste Organisation, für die ich jemals gearbeitet habe, offensichtlich, von Banken mit Tausenden von Filialen bis zu meinen eigenen Unternehmen. Die clientseitige Code-Basis-Lösung des Vertrauens allen zuZertifikate, einschließlich selbstsignierter Zertifikate, die von absolut jedem oder einer als Zertifizierungsstelle eingerichteten Schiedsstelle unterzeichnet wurden, sind ipso factonicht sicher. Es geht nur um Sicherheit. Es ist sinnlos. Sie führen ein privates, manipulationssicheres, antwort- und spritzwassergeschütztes Gespräch mit ... jemandem. Irgendjemand. Ein Mann in der Mitte. Ein Imitator. Irgendjemand. Sie können auch einfach Klartext verwenden.

Marquis von Lorne
quelle
2
Nur weil sich ein Server für die Verwendung von https entschieden hat, bedeutet dies nicht, dass die Person mit dem Client einen Mist über die Sicherheit für ihre eigenen Zwecke macht.
Gus
3
Ich bin überrascht, dass diese Antwort so sehr abgelehnt wurde. Ich würde gerne ein bisschen mehr verstehen warum. Es scheint, als würde EJP vorschlagen, dass Sie Option 2 nicht ausführen sollten, da dies eine schwerwiegende Sicherheitslücke zulässt. Könnte jemand erklären, warum (außer den Einstellungen vor der Bereitstellung) diese Antwort von geringer Qualität ist?
bis
2
Nun, ich denke alles. Was bedeutet "es liegt an ihnen, die erforderlichen Schritte zu unternehmen, um ihren Server nutzbar zu machen" ? Was muss ein Server-Betreiber tun, um es nutzbar zu machen? Welche Schritte haben Sie vor? Können Sie eine Liste von ihnen bereitstellen? Aber wie hängt das überhaupt mit dem Problem zusammen, das das OP gestellt hat? Er möchte wissen, wie der Client das selbstsignierte Zertifikat in Java akzeptieren kann. Dies ist eine einfache Angelegenheit, um dem Code Vertrauen zu verleihen, da das OP das Zertifikat für akzeptabel hält.
JWW
2
@EJP - Korrigieren Sie mich, wenn ich falsch liege, aber das Akzeptieren eines selbstsignierten Zertifikats ist eine clientseitige Richtlinienentscheidung. Es hat nichts mit serverseitigen Operationen zu tun. Der Kunde muss die Entscheidung treffen. Die Paritäten müssen zusammenarbeiten, um das Problem der Schlüsselverteilung zu lösen. Dies hat jedoch nichts damit zu tun, den Server nutzbar zu machen.
JWW
3
@EJP - Ich habe sicherlich nicht gesagt, "vertraue allen Zertifikaten" . Vielleicht fehlt mir etwas (oder Sie lesen zu viel in die Dinge hinein) ... Das OP hat das Zertifikat und es ist für ihn akzeptabel. Er will wissen, wie er ihm vertrauen kann. Ich spalte wahrscheinlich die Haare, aber das Zertifikat muss nicht offline geliefert werden. Eine Out-of-Band-Überprüfung sollte verwendet werden, dies ist jedoch nicht dasselbe wie "muss offline an den Client gesendet werden" . Er könnte sogar der Shop sein, der den Server und den Client produziert, sodass er über die erforderlichen A-priori- Kenntnisse verfügt.
JWW
0

Anstatt Keytool zu verwenden, wie im oberen Kommentar vorgeschlagen, können Sie in RHEL ab neueren Versionen von RHEL 6 update-ca-trust verwenden. Das Zertifikat muss im PEM-Format vorliegen. Dann

trust anchor <cert.pem>

Bearbeiten Sie /etc/pki/ca-trust/source/cert.p11-kit und ändern Sie "Zertifikatskategorie: anderer Eintrag" in "Zertifikatskategorie: Autorität". (Oder verwenden Sie sed, um dies in einem Skript zu tun.) Dann tun Sie es

update-ca-trust

Ein paar Einschränkungen:

  • Ich konnte auf meinem RHEL 6-Server kein "Vertrauen" finden und yum hat nicht angeboten, es zu installieren. Am Ende habe ich es auf einem RHEL 7-Server verwendet und die .p11-Kit-Datei kopiert.
  • Damit dies für Sie funktioniert, müssen Sie möglicherweise etwas tun update-ca-trust enable. Dadurch wird / etc / pki / java / cacerts durch einen symbolischen Link ersetzt, der auf / etc / pki / ca-trust / extrahiert / java / cacerts verweist. (Vielleicht möchten Sie zuerst die erste sichern.)
  • Wenn Ihr Java-Client Cacerts verwendet, die an einem anderen Speicherort gespeichert sind, möchten Sie diese manuell durch einen Symlink zu / etc / pki / ca-trust / extrahiert / java / cacerts ersetzen oder durch diese Datei ersetzen.
user66660
quelle
0

Ich hatte das Problem, dass ich eine URL an eine Bibliothek url.openConnection();weitergab, die anrief. Ich passte Jon-Daniels Antwort an.

public class TrustHostUrlStreamHandler extends URLStreamHandler {

    private static final Logger LOG = LoggerFactory.getLogger(TrustHostUrlStreamHandler.class);

    @Override
    protected URLConnection openConnection(final URL url) throws IOException {

        final URLConnection urlConnection = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()).openConnection();

        // adapated from
        // /programming/2893819/accept-servers-self-signed-ssl-certificate-in-java-client
        if (urlConnection instanceof HttpsURLConnection) {
            final HttpsURLConnection conHttps = (HttpsURLConnection) urlConnection;

            try {
                // Set up a Trust all manager
                final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    @Override
                    public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {
                    }

                    @Override
                    public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {
                    }
                } };

                // Get a new SSL context
                final SSLContext sc = SSLContext.getInstance("TLSv1.2");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                // Set our connection to use this SSL context, with the "Trust all" manager in place.
                conHttps.setSSLSocketFactory(sc.getSocketFactory());
                // Also force it to trust all hosts
                final HostnameVerifier allHostsValid = new HostnameVerifier() {
                    @Override
                    public boolean verify(final String hostname, final SSLSession session) {
                        return true;
                    }
                };

                // and set the hostname verifier.
                conHttps.setHostnameVerifier(allHostsValid);

            } catch (final NoSuchAlgorithmException e) {
                LOG.warn("Failed to override URLConnection.", e);
            } catch (final KeyManagementException e) {
                LOG.warn("Failed to override URLConnection.", e);
            }

        } else {
            LOG.warn("Failed to override URLConnection. Incorrect type: {}", urlConnection.getClass().getName());
        }

        return urlConnection;
    }

}

Mit dieser Klasse ist es möglich, eine neue URL zu erstellen mit:

trustedUrl = new URL(new URL(originalUrl), "", new TrustHostUrlStreamHandler());
trustedUrl.openConnection();

Dies hat den Vorteil, dass es lokalisiert ist und nicht die Standardeinstellung ersetzt URL.openConnection.

David Ryan
quelle