628 Stimmen

Auflösen von javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen Fehler?

Bearbeiten: Ich habe versucht, die Frage und die akzeptierte Antwort in einer vorzeigbareren Form in meinem Blog .

Hier ist die Originalausgabe.

Ich erhalte diesen Fehler:

Ausführliche Meldung sun.security.validator.ValidatorException: PKIX-Pfad Erstellung fehlgeschlagen:
sun.security.provider.certpath.SunCertPathBuilderException: kann nicht auf keinen gültigen Zertifizierungspfad zum angeforderten Ziel finden

javax.net.ssl.SSLHandshakeException verursachen: sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen: sun.security.provider.certpath.SunCertPathBuilderException: Unfähig, einen gültigen Zertifizierungspfad für das angeforderte Ziel zu finden

Ich verwende Tomcat 6 als Webserver. Ich habe zwei HTTPS-Webanwendungen auf verschiedenen Tomcats an verschiedenen Ports, aber auf demselben Rechner installiert. Sagen wir App1 (Port 8443) und App2 (Port 443). App1 stellt eine Verbindung zu App2 her. Wenn App1 eine Verbindung zu App2 herstellt, erhalte ich den oben genannten Fehler. Ich weiß, dass dieser Fehler sehr häufig auftritt, und habe in verschiedenen Foren und auf verschiedenen Websites viele Lösungen gefunden. Ich habe den folgenden Eintrag in server.xml der beiden Tomcats:

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

Auf jeder Website wird derselbe Grund angegeben: Das von app2 ausgestellte Zertifikat befindet sich nicht im vertrauenswürdigen Speicher von app1 jvm. Dies scheint auch dann zuzutreffen, wenn ich versuche, die gleiche URL im IE-Browser aufzurufen, was auch funktioniert (mit der Meldung Es gibt ein Problem mit dem Sicherheitszertifikat dieser Website. Hier sage ich weiter zu dieser Website). Aber wenn dieselbe URL von einem Java-Client aufgerufen wird (in meinem Fall), erhalte ich den oben genannten Fehler. Um sie in den Truststore aufzunehmen, habe ich diese drei Optionen ausprobiert:

Option 1

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

Option 2

Folgende Einstellung in der Umgebungsvariable

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

Option 3

Folgende Einstellung in der Umgebungsvariable

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

Ergebnis

Aber nichts funktionierte.

Was endlich funktionierte führt den Java-Ansatz aus, der in Wie behandelt man ungültige SSL-Zertifikate mit Apache HttpClient? von Pascal Thivent, d.h. die Ausführung des Programms InstallCert.

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

Ich frage mich, warum die drei oben genannten Ansätze nicht funktionieren, wenn ich die gleichen Werte in server.xml des App2-Servers und dieselben Werte im Truststore durch Setzen von

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

im Programm App1.

Für weitere Informationen stelle ich die Verbindung folgendermaßen her:

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

11voto

Ali Ismayilov Punkte 1687

Ein weiterer Grund könnte eine veraltete Version des JDK sein. Ich verwendete die JDK-Version 1.8.0_60. Ein einfaches Update auf die neueste Version löste das Zertifikatsproblem.

7voto

avp Punkte 2312

Ich benutzte jdk1.8.0_171 als ich das gleiche Problem hatte. Ich habe versucht, Top 2 Lösungen hier (Hinzufügen eines Zertifikats mit keytool und eine andere Lösung, die einen Hack in ihm hat), aber sie haben nicht für mich arbeiten.

Ich habe mein JDK aktualisiert auf 1.8.0_181 und es hat wunderbar funktioniert.

5voto

Bahadir Tasdemir Punkte 9128

DEPLOYABLE LÖSUNG (Alpine Linux)

Um dieses Problem in unseren Anwendungsumgebungen beheben zu können, haben wir folgende Linux-Terminalbefehle vorbereitet:

cd ~

Erzeugt eine Zertifizierungsdatei im Home-Verzeichnis.

apk add openssl

Dieser Befehl installiert openssl in Alpine Linux. Für andere Linux-Distributionen finden Sie entsprechende Befehle.

openssl s_client -connect <host-dns-ssl-belongs> < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

Erzeugt die benötigte Zertifizierungsdatei.

sudo $JAVA_HOME/bin/keytool -import -alias server_name -keystore $JAVA_HOME/lib/security/cacerts -file public.crt -storepass changeit -noprompt

Die erzeugte Datei wurde mit dem Programm "keytool" auf die JRE angewendet.

Nota: Bitte ersetzen Sie Ihre DNS durch <host-dns-ssl-belongs>

Anmerkung2: Bitte beachten Sie vorsichtig, dass -noprompt keine Verifizierungsmeldung (ja/nein) abfragt und -storepass changeit Parameter deaktiviert die Passwortabfrage und gibt das benötigte Passwort an (Standard ist 'changeit'). Mit diesen beiden Eigenschaften können Sie diese Skripte in Ihren Anwendungsumgebungen verwenden, z. B. zum Erstellen eines Docker-Images.

Anmerkung3 Wenn Sie Ihre Anwendung über Docker bereitstellen, können Sie die geheime Datei einmal generieren und in Ihre Anwendungsprojektdateien aufnehmen. Sie müssen sie dann nicht immer wieder neu erstellen.

4voto

tk_ Punkte 14471

Aus Sicherheitsgründen sollten wir in unserer Implementierung keine selbstsignierten Zertifikate verwenden. Wenn es jedoch um die Entwicklung geht, müssen wir oft Testumgebungen mit selbstsignierten Zertifikaten verwenden. Ich habe versucht, dieses Problem programmatisch in meinem Code zu beheben und bin gescheitert. Durch das Hinzufügen des Zertifikats zum JRE-Trust-Store konnte ich das Problem jedoch beheben. Bitte finden Sie unten Schritte,

  1. Laden Sie die Standortbescheinigung herunter,

  2. Kopieren Sie das Zertifikat (z.B.: cert_file.cer) in das Verzeichnis $JAVA_HOME \Jre\Lib\Security

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

  4. Importieren Sie das Zertifikat mit dem folgenden Befehl in einen Vertrauensspeicher,

keytool -import -alias ca -datei cert_file.cer -Keystore-Zertifikate -storepass changeit

Wenn Sie eine Fehlermeldung erhalten, die besagt, dass keytool nicht erkannt wird, dann beziehen sich darauf.

Tipo ja wie unten

Vertrauen Sie diesem Zertifikat: [Ja]

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

Update

Wenn Ihr Anwendungsserver jboss ist, versuchen Sie, die folgende Systemeigenschaft hinzuzufügen

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

Ich hoffe, das hilft!

4voto

Sharan Toor Punkte 71

Wenn Sie JDK 11 verwenden, befindet sich in dem Ordner kein JRE mehr. Der Speicherort für die Zertifizierungen ist jdk-11.0.11/lib/security/cacerts.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X