it-swarm.com.de

Beheben von javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: Fehler beim Erstellen des PKIX-Pfads?

Bearbeiten: - Es wurde versucht, die Frage und die akzeptierte Antwort bei mir auf ansehnlichere Weise zu formatieren Blog

Hier ist die ursprüngliche Ausgabe.

Ich erhalte diesen Fehler:

detaillierte Meldung Sun.security.validator.ValidatorException: PKIX-Pfadaufbau fehlgeschlagen:
Sun.security.provider.certpath.SunCertPathBuilderException: Es wurde kein gültiger Zertifizierungspfad für das angeforderte Ziel gefunden

javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: PKIX-Pfadaufbau fehlgeschlagen: Sun.security.provider.certpath.SunCertPathBuilderException: Es wurde kein gültiger Zertifizierungspfad für das angeforderte Ziel gefunden

Ich benutze Tomcat 6 als Webserver. Ich habe zwei HTTPS-Webanwendungen auf verschiedenen Tomcats an verschiedenen Ports, aber auf demselben Computer installiert. Sagen Sie App1(port 8443) und App2(port 443). App1 verbindet sich mit App2. Wenn App1 eine Verbindung zu App2 herstellt, wird der obige Fehler angezeigt. Ich weiß, dass dies ein sehr häufiger Fehler ist, und bin daher auf viele Lösungen in verschiedenen Foren und auf verschiedenen Websites gestoßen. Ich habe den folgenden Eintrag in server.xml beider Kater:

keystoreFile="c:/.keystore" 
keystorePass="changeit"

Auf jeder Site wird derselbe Grund angegeben, warum das von App2 angegebene Zertifikat nicht im vertrauenswürdigen Speicher von App1 JVM gespeichert ist. Dies scheint auch zuzutreffen, als ich im IE Browser versucht habe, auf dieselbe URL zuzugreifen. Dies funktioniert. Aber wenn die gleiche URL von Java Client (in meinem Fall) getroffen wird, erhalte ich den obigen Fehler. Um es in den Truststore zu legen, habe ich diese drei Optionen ausprobiert:

Option1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Option2 Einstellung unten in Umgebungsvariable

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Option3 Einstellung unten in Umgebungsvariable

Java_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Aber nichts hat funktioniert .

Was zuletzt funktioniert hat ist die Ausführung des in vorgeschlagenen Java-Ansatzes. Wie man ungültige SSL-Zertifikate mit Apache behandelt HttpClient? von Pascal Thivent dh Ausführen des Programms InstallCert.

Aber dieser Ansatz ist in Ordnung für das Devbox-Setup, aber ich kann ihn nicht in der Produktionsumgebung verwenden.

Ich frage mich, warum drei Ansätze, die oben erwähnt wurden, nicht funktioniert haben, als ich die gleichen Werte in server.xml von app2 Server und die gleichen Werte in Truststore durch Einstellung erwähnt habe

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

im app1 Programm.

Weitere Informationen dazu, wie ich die Verbindung herstelle:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();

  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());
367
M Sach

Sie müssen das Zertifikat für App2 zur Truststore-Datei der verwendeten JVM hinzufügen, die sich unter %Java_HOME%\lib\security\cacerts befindet.

Zuerst können Sie überprüfen, ob sich Ihr Zertifikat bereits im Truststore befindet, indem Sie den folgenden Befehl ausführen: keytool -list -keystore "%Java_HOME%/jre/lib/security/cacerts" (Sie müssen kein Kennwort angeben)

Wenn Ihr Zertifikat fehlt, können Sie es herunterladen, indem Sie es mit Ihrem Browser herunterladen und mit dem folgenden Befehl zum Truststore hinzufügen:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

Nach dem Import können Sie den ersten Befehl erneut ausführen, um zu überprüfen, ob Ihr Zertifikat hinzugefügt wurde.

Sun/Oracle-Informationen finden Sie hier .

357
SimonSez

javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: PKIX-Pfadaufbau fehlgeschlagen: Sun.security.provider.certpath.SunCertPathBuilderException: Es wurde kein gültiger Zertifizierungspfad für das angeforderte Ziel gefunden

• Als ich die Fehlermeldung erhielt, habe ich versucht, die Bedeutung des Ausdrucks bei Google zu ermitteln, und festgestellt, dass dieses Problem auftritt, wenn ein Server sein HTTPS-SSL-Zertifikat ändert und unsere ältere Version von Java das nicht erkennt Stammzertifizierungsstelle (CA).

• Wenn Sie in Ihrem Browser auf die HTTPS-URL zugreifen können, können Sie Java aktualisieren, um die Stammzertifizierungsstelle zu erkennen.

• Wechseln Sie in Ihrem Browser zu der HTTPS-URL, auf die Java nicht zugreifen konnte. Klicken Sie auf die HTTPS-Zertifikatskette (im Internet Explorer gibt es ein Schlosssymbol). Klicken Sie auf das Schloss, um das Zertifikat anzuzeigen.

• Gehen Sie zu "Details" des Zertifikats und "In Datei kopieren". Kopieren Sie es im Format Base64 (.cer). Es wird auf Ihrem Desktop gespeichert.

• Installieren Sie das Zertifikat, indem Sie alle Warnungen ignorieren.

• Auf diese Weise habe ich die Zertifikatinformationen der URL erfasst, auf die ich zugreifen wollte.

Jetzt musste ich meine Java -Version erstellen, um über das Zertifikat Bescheid zu wissen, damit es die Erkennung der URL nicht verweigert. In diesem Zusammenhang muss ich erwähnen, dass ich gegoogelt habe, dass die Stammzertifikatsinformationen standardmäßig im Speicherort von JDK \ jre\lib\security gespeichert bleiben und das Standardkennwort für den Zugriff lautet: changeit. =

Um die Cacerts-Informationen anzuzeigen, gehen Sie wie folgt vor:

• Klicken Sie auf Start Button -> Run

• Geben Sie cmd ein. Der Befehl Eingabeaufforderung wird geöffnet (möglicherweise müssen Sie ihn als Administrator öffnen).

• Wechseln Sie in Ihr Verzeichnis Java/jreX/bin

• Geben Sie Folgendes ein

keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

Es gibt die Liste der aktuellen Zertifikate an, die im Keystore enthalten sind. Es sieht ungefähr so ​​aus:

C:\Dokumente und Einstellungen\NeelanjanaG> keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

Geben Sie das Keystore-Passwort ein: changeit

Schlüsselspeichertyp: jks

Keystore-Anbieter: Sun.

Ihr Keystore enthält 44 Einträge

verisignclass3g2ca, 26. März 2004, trustedCertEntry,

Zertifikat-Fingerabdruck (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9

entrustclientca, 9. Januar 2003, trustedCertEntry,

Zertifikat-Fingerabdruck (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4

thawtepersonalbasicca, 13. Februar 1999, trustedCertEntry,

Zertifikat-Fingerabdruck (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41

addtrustclass1ca, 1. Mai 2006, trustedCertEntry,

Zertifikat-Fingerabdruck (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC

verisignclass2g3ca, 26. März 2004, trustedCertEntry,

Zertifikat-Fingerabdruck (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6

• Jetzt musste ich das zuvor installierte Zertifikat in die cacerts aufnehmen.

• Hierzu ist wie folgt vorzugehen:

keytool –import –noprompt –trustcacerts –alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD

Wenn Sie Java 7 verwenden:

keytool –importcert –trustcacerts –alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

• Anschließend werden die Zertifikatinformationen in die Cacert-Datei eingefügt.

Es ist die Lösung, die ich für die oben erwähnte Ausnahme gefunden habe !!

162
NDeveloper

Wie es funktioniert in Tomcat 7

Ich wollte ein selbstsigniertes Zertifikat in einer Tomcat-App unterstützen, aber das folgende Snippet funktionierte nicht

import Java.io.DataOutputStream;
import Java.net.HttpURLConnection;
import Java.net.URL;

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

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "{}";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    }
}

das hat mein Problem gelöst:

1) Laden Sie die .crt -Datei herunter

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • ersetzen Sie <your domain> durch Ihre Domain (z. B. jossef.com).

2) Wenden Sie die Datei .crt in Javas Zertifikatspeicher cacerts an

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <Java HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
  • ersetzen Sie <your domain> durch Ihre Domain (z. B. jossef.com).
  • ersetzen Sie <Java HOME> durch Ihr Java Ausgangsverzeichnis

3) Hack es

Obwohl ich mein Zertifikat in den Standardzertifikatsspeichern von Java installiert habe, Tomcat ignoriert dies (anscheinend ist es nicht für die Verwendung von Java-Standardzertifikatsspeichern konfiguriert).

Um dies zu hacken, fügen Sie Folgendes irgendwo in Ihren Code ein:

String certificatesTrustStorePath = "<Java HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...
33
Jossef Harush

In meinem Fall bestand das Problem darin, dass der Webserver nur das Zertifikat und die Zwischenzertifizierungsstelle sendete, nicht die Stammzertifizierungsstelle. Durch Hinzufügen dieser JVM-Option wurde das Problem behoben: -Dcom.Sun.security.enableAIAcaIssuers=true

Die Zugriffsmethode caIssuers der Erweiterung Authority Information Access wird unterstützt. Es ist aus Kompatibilitätsgründen standardmäßig deaktiviert und kann aktiviert werden, indem die Systemeigenschaft com.Sun.security.enableAIAcaIssuers auf den Wert true gesetzt wird.

Bei Festlegung auf "true" verwendet die PKIX-Implementierung von CertPathBuilder von Sun die Informationen in der AIA-Erweiterung eines Zertifikats (zusätzlich zu den angegebenen CertStores), um das ausstellende CA-Zertifikat zu ermitteln, sofern es sich um einen URI vom Typ "ldap", "http" oder "ftp" handelt.

Quelle

8
Guillaume

Meine cacerts Akte war total leer. Ich habe dieses Problem gelöst, indem ich die cacerts-Datei von meinem Windows-Computer kopiert habe (das verwendet Oracle Java 7) und sie auf meine Linux-Box (OpenJDK) kopiert habe.

cd %Java_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

und dann auf dem Linux-Rechner

cp /tmp/cacerts /etc/ssl/certs/Java/cacerts

Bisher hat es super geklappt.

5

Ein weiterer Grund könnte eine veraltete Version von JDK sein. Ich habe die jdk-Version 1.8.0_60 verwendet und durch einfaches Aktualisieren auf die neueste Version das Zertifikatproblem behoben.

5
Ali Ismayilov

Der folgende Code funktioniert für mich:

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

import javax.net.ssl.X509TrustManager;

public 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[] {};
}
}

HttpsURLConnection conn = null;
            URL url = new URL(serviceUrl);
            conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new Java.security.SecureRandom());  

             conn.setSSLSocketFactory(sc.getSocketFactory());
5
Sandip S.

Mit Tomcat 7 unter Linux hat dies den Trick getan.

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Unter Linux ist $Java_HOME nicht immer eingerichtet, aber normalerweise /etc/alternatives/jre zeigt auf $Java_HOME/jre

4
Cedric Simon

Für mich trat dieser Fehler auch auf, als ich versuchte, eine Verbindung zu einem Prozess hinter einem NGINX-Reverse-Proxy herzustellen, der das SSL handhabte.

Es stellte sich heraus, dass es sich bei dem Problem um ein Zertifikat handelte, bei dem nicht die gesamte Zertifikatskette verkettet war. Als ich Zwischenzertifikate hinzufügte, war das Problem gelöst.

Hoffe das hilft.

4
YaDa

Ich habe jdk1.8.0_171 verwendet, als ich auf dasselbe Problem gestoßen bin. Ich habe hier die Top-2-Lösungen ausprobiert (Hinzufügen eines Zertifikats mit Keytool und einer anderen Lösung, die einen Hack enthält), aber sie haben bei mir nicht funktioniert.

Ich habe mein JDK auf 1.8.0_181 aktualisiert und es hat wie ein Zauber funktioniert.

4
avp

ich habe ein kleines Win32 (WinXP 32bit Testet) dummes Cmd (Kommandozeilen) Skript geschrieben, das nach allen Java Versionen in Programmdateien sucht und ihnen ein Zertifikat hinzufügt. Das Passwort muss die Standardeinstellung "changeit" sein oder es muss selbst im Skript geändert werden :-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\Java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause
2
mons droid

Verwenden Sie den Befehl "ps -ef | grep Tomcat", wenn Tomcat auf einem Ubuntu-Server ausgeführt wird, um herauszufinden, welches Java verwendet wird:

Stichprobe:

/home/mcp01$ **ps -ef |grep Tomcat**
Tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/Java/jdk1.7.0_15/bin/Java** -Djava.util.logging.config.file=/var/lib/Tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.Apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/Tomcat7/endorsed -classpath /usr/share/Tomcat7/bin/bootstrap.jar:/usr/share/Tomcat7/bin/Tomcat-juli.jar -Dcatalina.base=/var/lib/Tomcat7 -Dcatalina.home=/usr/share/Tomcat7 -Djava.io.tmpdir=/tmp/Tomcat7-Tomcat7-tmp org.Apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto Tomcat

Dann können wir uns ansehen: cd /usr/local/Java/jdk1.7.0_15/jre/lib/security

Die Standarddatei cacerts befindet sich hier. Fügen Sie das nicht vertrauenswürdige Zertifikat ein.

1
oraclesoon

Ich habe auch dieses Problem.

Ich habe fast alles versucht, indem ich das SSL-Zertifikat zu .keystore hinzugefügt habe, aber es funktionierte nicht mit Java1_6_x. Für mich hat es geholfen, wenn wir eine neuere Version von Java verwenden, Java1_8_x als JVM.

0
Nubian

Für MacOS X unten ist der genaue Befehl, der für mich funktioniert hat, wo ich mit Doppelhypern in der Option 'importcert' versuchen musste, was funktioniert hat:

Sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit
0
apandey846

aus Sicherheitsgründen sollten wir in unserer Implementierung keine selbstsignierten Zertifikate verwenden. Wenn es jedoch um die Entwicklung geht, müssen wir häufig Testumgebungen verwenden, die selbst signierte Zertifikate haben. Ich habe versucht, dieses Problem programmgesteuert in meinem Code zu beheben, und es ist fehlgeschlagen. Durch das Hinzufügen des Zertifikats zum Trust-Store von jre wurde das Problem behoben. Finden sie unten schritte,

  1. Laden Sie das Site-Zertifikat herunter.

  2. Kopieren Sie das Zertifikat (zB cert_file.cer) in das Verzeichnis $ Java_HOME\Jre\Lib\Security

  3. Öffnen Sie CMD in Administrator und ändern Sie das Verzeichnis in $ Java_HOME\Jre\Lib\Security

  4. Importieren Sie das Zertifikat mit dem folgenden Befehl in einen Trust Store.

keytool -import -alias ca -file cert_file.cer -keystore cacerts -storepass changeit

Wenn Sie eine Fehlermeldung erhalten, dass das Keytool nicht erkennbar ist, lesen Sie dies nach.

Geben Sie yes wie unten ein

Vertrauen Sie diesem Zertifikat: [Ja]

  1. Versuchen Sie nun, Ihren Code auszuführen oder programmgesteuert mit Java auf die URL zuzugreifen.

Update

Wenn Ihr App-Server JBoss ist, versuchen Sie, die folgende Systemeigenschaft hinzuzufügen

System.setProperty("org.jboss.security.ignoreHttpsHost","true");

Hoffe das hilft!

0
tk_

Ich stoße mit AndroidStudio, Charles Proxy, JUnit und Robolectric auf dieses Problem. Danke @SimonSez, ich konnte das Problem lösen.

Bitte beachten Sie: Da der Schlüsselpunkt in der Änderung von cacerts liegt, kann dies zu Problemen führen (zB Aktualisierung der IDE ). Ich würde Ihnen empfehlen kopiere die ursprüngliche cacerts Datei in ein separates Verzeichnis und bearbeite sie bei Bedarf.

  1. %Java_HOME% - Android verwendet ein anderes JavaHome. Den vollständigen Pfad finden Sie auf der Registerkarte UnitTests resulr. In meinem Fall ist es /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home

    enter image description here

  2. Charles-Zertifikat herunterladen (z. B. Ordner Downloads)

  3. Führen Sie den Befehl aus

    Sudo keytool -import -noprompt -trustcacerts -alias charles -file <path to Charles certificate.pem> -keystore "Java_HOME/jre/lib/security/cacerts" -storepass changeit

    Zum Beispiel

    Sudo keytool -import -noprompt -trustcacerts -alias charles -file ~/Downloads/charles-ssl-proxying-certificate.pem -keystore "/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts" -storepass changeit

Der offizielle Charles Doc

0
yoAlex5