386 Stimmen

Java: sun.security.provider.certpath.SunCertPathBuilderException: es konnte kein gültiger Zertifikatspfad zum angeforderten Ziel gefunden werden

Ich habe eine Klasse, die eine Datei von einem https Server herunterlädt. Wenn ich es ausführe, werden viele Fehler zurückgegeben. Es scheint, dass ich ein Problem mit meinem Zertifikat habe. Ist es möglich, die Client-Server-Authentifizierung zu ignorieren? Wenn ja, wie?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
    static FileOutputStream fos;

    public void DownloadFile(String URI, String Request) throws Exception
    {
        java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
                "Lang=EN&AuthToken=package", null);
        System.out.println("URI-Abfrage: " + uri.toString());

        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
        httpclient.start();
        try {
            Future future = httpclient.execute(
                    new HttpAsyncGet(uri),
                    new ResponseCallback(), null);

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nAnforderung erfolgreich ausgeführt");
            } else {
                System.out.println("Anforderung fehlgeschlagen");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Ausnahme: " + e.getMessage());
        }
        finally {
            System.out.println("Herunterfahren");
            httpclient.shutdown();
        }
        System.out.println("Fertig");  

    }

    static class ResponseCallback extends AsyncCharConsumer {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Antwort: " + response.getStatusLine());
             System.out.println("Header: " + response.toString());
             try {   
                 //if(response.getStatusLine().getStatusCode()==200)
                     fos = new FileOutputStream( "Response.html" );
             }catch(Exception e){
                 System.out.println("[onResponseReceived] Ausnahme: " + e.getMessage());
             }
        }

        @Override
        protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
            try
            {
                while (buf.hasRemaining()) 
                {
                    //System.out.print(buf.get());
                    fos.write(buf.get());
                }
            }catch(Exception e)
            {
                System.out.println("[onCharReceived] Ausnahme: " + e.getMessage());
            }
        }

        @Override
        protected void onCleanup() {
            try
            {             
                if(fos!=null)
                    fos.close();
            }catch(Exception e){
                System.out.println("[onCleanup] Ausnahme: " + e.getMessage());         
            }
             System.out.println("onCleanup()");
        }

        @Override
        protected Boolean buildResult() {
            return Boolean.TRUE;
        }

    }
}

Fehler:

URI-Abfrage: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O-Fehler: Allgemeines SSLEngine-Problem
javax.net.ssl.SSLHandshakeException: Allgemeines SSLEngine-Problem
    at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
    at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
    at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
    at java.lang.Thread.run(Unknown Source)
Verursacht durch: javax.net.ssl.SSLHandshakeException: Allgemeines SSLEngine-Problem
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
    ... 9 more
Verursacht durch: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 21 more
onCleanup()

[DownloadFile] Ausnahme: javax.net.ssl.SSLHandshakeException: Allgemeines SSLEngine-Problem
Herunterfahren
Fertig

5 Stimmen

Einmal habe ich diesen Fehler bekommen und unser Sicherheitsteam kontaktiert, und es stellte sich heraus, dass ich das JAR patchen musste, das wir verwendet haben, da unser Team ein veraltetes von der Firma bereitgestelltes benutzte. Nur als Information für alle anderen, die sich in einer ähnlichen Situation befinden könnten.

0 Stimmen

Ich habe dieses PKIX-Problem in zwei Fällen erhalten, beim Herunterladen der Maven-Abhängigkeit direkt aus dem Internet anstelle des Caches meiner Organisation. Dies wurde durch die Korrektur der setting.xml-Datei behoben. Das zweite Mal hatte ich dieses Problem, als ich versuchte, auf Microsoft URI für oAuth-Token zuzugreifen. Dies wurde durch Hinzufügen der cacert-Datei in meinen JDK-Pfad behoben.

289voto

Maxim Mazin Punkte 3566

Das Problem tritt auf, wenn Ihr Server ein selbst signiertes Zertifikat hat. Um dies zu umgehen, können Sie dieses Zertifikat zur Liste der vertrauenswürdigen Zertifikate Ihrer JVM hinzufügen.

In diesem Artikel beschreibt der Autor, wie Sie das Zertifikat aus Ihrem Browser abrufen und zur cacerts-Datei Ihrer JVM hinzufügen können. Sie können entweder die Datei JAVA_HOME/jre/lib/security/cacerts bearbeiten oder Ihre Anwendung mit dem Parameter -Djavax.net.ssl.trustStore ausführen. Überprüfen Sie auch, welches JDK/JRE Sie verwenden, da dies oft eine Quelle der Verwirrung ist.

Siehe auch: Wie werden SSL-Zertifikatservernamen aufgelöst/Kann ich alternative Namen mit keytool hinzufügen? Wenn Sie auf die Ausnahme java.security.cert.CertificateException: No name matching localhost found stoßen.

10 Stimmen

Dies hat für mich nicht funktioniert. Ich habe das Root-Zertifikat und das Kettenzertifikat installiert, aber Tomcat-7 meldet immer noch eine ValidatorException, die durch "kann keinen gültigen Zertifikatpfad zum angeforderten Ziel finden" verursacht wird. Gibt es einen Weg, dies zu debuggen?

1 Stimmen

Das Problem tritt auch bei einem Zertifikat auf, das von jemand anderem signiert wurde und nicht vertrauenswürdig ist.

3 Stimmen

Großartig! Es funktioniert! Vergiss einfach nicht, dass du sowohl jre als auch jdk haben könntest, und dass beide ihre cacerts aktualisiert werden müssen

198voto

Das ist, was für mich zuverlässig auf macOS funktioniert. Stellen Sie sicher, dass Sie example.com und 443 durch den tatsächlichen Hostnamen und Port ersetzen, mit dem Sie sich verbinden möchten, und geben Sie einen benutzerdefinierten Alias an. Der erste Befehl lädt das bereitgestellte Zertifikat vom entfernten Server herunter und speichert es lokal im x509-Format. Der zweite Befehl lädt das gespeicherte Zertifikat in den SSL-Truststore von Java.

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit

Unter Windows über Git Bash oder WSL sieht der erste Befehl etwas anders aus:

openssl s_client -connect git.css.ch:443  -prexit > ~/cert.txt
openssl x509 -in ~/cert.txt -out ~/example.crt

5 Stimmen

Funktioniert für mich warum? Du musst eine Erklärung geben.

0 Stimmen

Openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt - Was ist example.crt im Befehl? Ich habe ein .pem-Zertifikat, das ich hier angeben muss.

3 Stimmen

.crt und .pem sind häufig verwendete Dateierweiterungen für dasselbe Dateiformat. Wenn Sie die Datei bereits haben, führen Sie einfach den zweiten Befehl aus und übergeben Sie sie dem Argument -file.

59voto

Robin Punkte 6259
  1. Exportieren Sie das SSL-Zertifikat mit Firefox. Sie können es exportieren, indem Sie die URL im Browser aufrufen und dann die Option zum Exportieren des Zertifikats auswählen. Nehmen wir an, der Dateiname der Zertifikatsdatei lautet your.ssl.server.name.crt
  2. Gehen Sie zu Ihrem JRE_HOME/bin oder JDK/JRE/bin
  3. Geben Sie den Befehl ein
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Starten Sie Ihren Java-Prozess neu

23 Stimmen

Wenn Sie nach einem Passwort gefragt werden, verwenden Sie das Standard-Keystore-Passwort changeit (stackoverflow.com/a/22782035/1304830). Stellen Sie außerdem sicher, dass Sie cmd als Administrator ausführen.

55voto

Stephan Oudmaijer Punkte 781

Ich hatte dasselbe Problem mit einem gültigen signierten Wildcard-Zertifikat von Symantec.

Versuchen Sie zunächst, Ihre Java-Anwendung mit -Djavax.net.debug=SSL auszuführen, um zu sehen, was wirklich passiert.

Letztendlich habe ich das Zwischenzertifikat importiert, das die Zertifikatskette unterbrach.

Ich habe das fehlende Zwischenzertifikat von Symantec heruntergeladen (den Download-Link zum fehlenden Zertifikat im SSL-Handshake-Protokoll sehen Sie hier: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer in meinem Fall).

Und ich habe das Zertifikat im Java-Keystore importiert. Nach dem Importieren des Zwischenzertifikats hat mein Wildcard-SSL-Zertifikat endlich funktioniert:

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer

0 Stimmen

Dies war der Fall:

5 Stimmen

Um Verwirrung zu vermeiden, führen Sie Java (oder jcurl) mit Debug-Parametern aus, um den remote "Zertifikatskette" in den Protokollen zu sehen, dann greifen Sie den "CN" im Truststore explizit ab (anstelle des Standardwerts) wie folgt, falls nicht vorhanden, müssen Sie hinzufügen. ssllabs.com/ssltest/analyze.html zeigt an, ob die Server-Zertifikate eine unvollständige Kette haben und enthält Zwischenzertifikate, die hinzugefügt werden müssen. -Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs

0 Stimmen

Und natürlich der offizielle Artikel zur Fehlerbehebung bei SSL-Problemen: docs.oracle.com/javase/7/docs/technotes/guides/security/jsse‌​/… blogs.oracle.com/java-platform-group/entry/…

38voto

bhdrk Punkte 3129

Die Antwort von @Gabe Martin-Dempesy hat mir geholfen. Und ich habe ein kleines Skript dazu geschrieben. Die Verwendung ist sehr einfach.

Installieren Sie ein Zertifikat vom Host:

> sudo ./java-cert-importer.sh example.com

Entfernen Sie das bereits installierte Zertifikat.

> sudo ./java-cert-importer.sh example.com --delete

java-cert-importer.sh

#!/usr/bin/env bash

# Exit bei Fehler
set -e

# Stellen Sie sicher, dass das Skript als root ausgeführt wird
if [ "$EUID" -ne 0 ]
  then echo "WARNUNG: Bitte als Root (sudo) ausführen"
  exit 1
fi

# Überprüfen, ob erforderliche Befehle vorhanden sind
command -v openssl >/dev/null 2>&1 || { echo "Erforderlicher Befehl 'openssl' nicht installiert. Abbruch." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Erforderlicher Befehl 'keytool' nicht installiert. Abbruch." >&2; exit 1; }

# Befehlszeilenargumente erhalten
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Überprüfen des Host-Arguments
if [ ! ${host} ]; then
cat << EOF
Bitte erforderliche Parameter eingeben

Verwendung:  ./java-cert-importer.sh  [  | Standard=443 ] [ -d | --delete ]

EOF
exit 1
fi;

if [ "$JAVA_HOME" ]; then
    javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
    javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
    javahome="$(/usr/libexec/java_home)/jre"
fi

if [ ! "$javahome" ]; then
    echo "WARNUNG: Java-Startverzeichnis konnte nicht gefunden werden."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARNUNG: Das erkannte Java-Startverzeichnis existiert nicht: $javahome"
    exit 1
fi

echo "Erkanntes Java-Startverzeichnis: $javahome"

# Setzen des Dateipfads für die cacerts-Datei
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Zertifikat für ${host} gelöscht"
    exit 0
fi

# Host-Info vom Benutzer erhalten
#read -p "Serverhost eingeben (z.B. example.com) : " host
#read -p "Serverport eingeben (Standard 443) : " port

# Temporäre Datei erstellen
tmpfile="/tmp/${host}.$$.crt"

# Java cacerts-Backup-Datei erstellen
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts-Backup: ${cacertsbackup}"

# Zertifikat vom angegebenen Host erhalten
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Zertifikat in die Java-cacerts-Datei importieren
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Temporäre Zertifikatsdatei löschen
rm ${tmpfile}

# Überprüfen des Zertifikataliasnamens (gleich mit Host), das erfolgreich importiert wurde
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Aliasname: ${host}")

# Benutzer die Ergebnisse anzeigen
if [ "$result" ]; then
    echo "Erfolg: Zertifikat wurde in Java-cacerts für ${host} importiert";
else
    echo "Fehler: Etwas ist schiefgelaufen";
fi;

1 Stimmen

Funktioniert einwandfrei. Gute Arbeit! . So funktioniert es: Starten Sie Ihren SSL-Dienst (wenn er nicht läuft) und führen Sie den Befehl wie erklärt aus (z.B. ./java-cert-importer.sh beispiel.com 1234). Das war's.

1 Stimmen

Funktioniert super. Ich habe den Fehler auf einem Jenkins-Server bekommen, der sich mit einer externen API verbindet, die ihr Zertifikat ändert und meine Builds fehlschlägt. Das löst mein Problem.

2 Stimmen

Oracle hätte von Anfang an so etwas bereitstellen sollen oder niemals ihre eigene schreckliche SSL-Lösung erstellen sollen. Die Verwaltung von SSL-Zertifikaten sollte die Aufgabe eines Betriebssystems sein.

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