it-swarm.com.de

Gültiger Zertifizierungspfad zum angeforderten Ziel konnte nicht gefunden werden, auch nachdem das Zertifikat importiert wurde

Ich habe einen Java-Client, der versucht, auf einen Server mit einem selbstsignierten Zertifikat zuzugreifen.

Wenn ich versuche, auf dem Server zu posten, erhalte ich die folgende Fehlermeldung:

es wurde kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden

Nach einigen Nachforschungen zu diesem Thema habe ich dann folgendes getan.

  1. Der Domänenname meines Servers wurde als root.cer-Datei gespeichert.
  2. In der JRE meines Glassfish-Servers habe ich Folgendes ausgeführt:
    keytool -import -alias example -keystore cacerts -file root.cer
  3. Um zu überprüfen, ob das Zertifikat erfolgreich zu meinem Zertifikat hinzugefügt wurde, habe ich Folgendes getan:
    keytool -list -v -keystore cacerts
    Ich kann sehen, dass das Zertifikat vorhanden ist.
  4. Dann habe ich Glassfish neu gestartet und den 'Post' zurückgezogen.

Ich bekomme immer noch den gleichen Fehler.

Ich habe das Gefühl, dies ist so, weil mein Glassfish nicht wirklich die von mir geänderte cacert-Datei liest, sondern vielleicht eine andere.

Hat einer von euch dieses Problem gehabt und kann mich in die richtige Richtung schieben?

158
TheCoder

Unglücklicherweise - es könnten viele Dinge sein - und viele App-Server und andere Java-Wrapper neigen dazu, mit Eigenschaften zu spielen und ihre "eigenen" Eigenschaften von Schlüsselbändern zu übernehmen. Es kann also etwas ganz anderes aussehen. 

Kurz gesagt, ich würde es versuchen:

Java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...

um zu sehen, ob das hilft. Anstelle von "all" können Sie auch "ssl", Schlüsselmanager und Vertrauensmanager festlegen. Dies kann in Ihrem Fall hilfreich sein. Wenn Sie die Option auf "Hilfe" setzen, wird auf den meisten Plattformen etwas angezeigt.

Unabhängig davon - stellen Sie sicher, dass Sie den Unterschied zwischen dem Schlüsselspeicher (in dem Sie den privaten Schlüssel und das Zertifikat besitzen, mit dem Sie Ihre eigene Identität nachweisen) und dem Vertrauensspeicher (der bestimmt, wem Sie vertrauen) - und der Tatsache, dass Ihre eigene Identität auch besteht, vollständig verstehen hat eine "Vertrauenskette" zur Wurzel - die sich von jeder Kette zu einer Wurzel unterscheidet, die Sie benötigen, um herauszufinden, "wem" Sie vertrauen.

all            turn on all debugging
ssl            turn on ssl debugging

The   following can be used with ssl:
    record       enable per-record tracing
    handshake    print each handshake message
    keygen       print key generation data
    session      print session activity
    defaultctx   print default SSL initialization
    sslctx       print SSLContext tracing
    sessioncache print session cache tracing
    keymanager   print key manager tracing
    trustmanager print trust manager tracing
    pluggability print pluggability tracing

    handshake debugging can be widened with:
    data         hex dump of each handshake message
    verbose      verbose handshake message printing

    record debugging can be widened with:
    plaintext    hex dump of record plaintext
    packet       print raw SSL/TLS packets

Quelle: # See http://download.Oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Debug

123

Hier ist die Lösung, folgen Sie dem folgenden Link Schritt für Schritt:

http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

Java-DATEI: Was fehlt im Blog

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */



import Java.io.*;
import Java.net.URL;

import Java.security.*;
import Java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

    public static void main(String[] args) throws Exception {
    String Host;
    int port;
    char[] passphrase;
    if ((args.length == 1) || (args.length == 2)) {
        String[] c = args[0].split(":");
        Host = c[0];
        port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
        String p = (args.length == 1) ? "changeit" : args[1];
        passphrase = p.toCharArray();
    } else {
        System.out.println("Usage: Java InstallCert <Host>[:port] [passphrase]");
        return;
    }

    File file = new File("jssecacerts");
    if (file.isFile() == false) {
        char SEP = File.separatorChar;
        File dir = new File(System.getProperty("Java.home") + SEP
            + "lib" + SEP + "security");
        file = new File(dir, "jssecacerts");
        if (file.isFile() == false) {
        file = new File(dir, "cacerts");
        }
    }
    System.out.println("Loading KeyStore " + file + "...");
    InputStream in = new FileInputStream(file);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(in, passphrase);
    in.close();

    SSLContext context = SSLContext.getInstance("TLS");
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
    SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
    context.init(null, new TrustManager[] {tm}, null);
    SSLSocketFactory factory = context.getSocketFactory();

    System.out.println("Opening connection to " + Host + ":" + port + "...");
    SSLSocket socket = (SSLSocket)factory.createSocket(Host, port);
    socket.setSoTimeout(10000);
    try {
        System.out.println("Starting SSL handshake...");
        socket.startHandshake();
        socket.close();
        System.out.println();
        System.out.println("No errors, certificate is already trusted");
    } catch (SSLException e) {
        System.out.println();
        e.printStackTrace(System.out);
    }

    X509Certificate[] chain = tm.chain;
    if (chain == null) {
        System.out.println("Could not obtain server certificate chain");
        return;
    }

    BufferedReader reader =
        new BufferedReader(new InputStreamReader(System.in));

    System.out.println();
    System.out.println("Server sent " + chain.length + " certificate(s):");
    System.out.println();
    MessageDigest sha1 = MessageDigest.getInstance("SHA1");
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    for (int i = 0; i < chain.length; i++) {
        X509Certificate cert = chain[i];
        System.out.println
            (" " + (i + 1) + " Subject " + cert.getSubjectDN());
        System.out.println("   Issuer  " + cert.getIssuerDN());
        sha1.update(cert.getEncoded());
        System.out.println("   sha1    " + toHexString(sha1.digest()));
        md5.update(cert.getEncoded());
        System.out.println("   md5     " + toHexString(md5.digest()));
        System.out.println();
    }

    System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
    String line = reader.readLine().trim();
    int k;
    try {
        k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
    } catch (NumberFormatException e) {
        System.out.println("KeyStore not changed");
        return;
    }

    X509Certificate cert = chain[k];
    String alias = Host + "-" + (k + 1);
    ks.setCertificateEntry(alias, cert);

    OutputStream out = new FileOutputStream("jssecacerts");
    ks.store(out, passphrase);
    out.close();

    System.out.println();
    System.out.println(cert);
    System.out.println();
    System.out.println
        ("Added certificate to keystore 'jssecacerts' using alias '"
        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
    StringBuilder sb = new StringBuilder(bytes.length * 3);
    for (int b : bytes) {
        b &= 0xff;
        sb.append(HEXDIGITS[b >> 4]);
        sb.append(HEXDIGITS[b & 15]);
        sb.append(' ');
    }
    return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

    private final X509TrustManager tm;
    private X509Certificate[] chain;

    SavingTrustManager(X509TrustManager tm) {
        this.tm = tm;
    }

    public X509Certificate[] getAcceptedIssuers() {
        throw new UnsupportedOperationException();
    }

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

    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        this.chain = chain;
        tm.checkServerTrusted(chain, authType);
    }
    }

}
17
user6258309

Sie müssen die JSSE-Systemeigenschaften konfigurieren und insbesondere auf den Zertifikatspeicher des Clients verweisen. 

Über die Kommandozeile:

Java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client

oder über Java-Code:

import Java.util.Properties;
    ...
    Properties systemProps = System.getProperties();
    systemProps.put("javax.net.ssl.keyStorePassword","passwordForKeystore");
    systemProps.put("javax.net.ssl.keyStore","pathToKeystore.ks");
    systemProps.put("javax.net.ssl.trustStore", "pathToTruststore.ts");
    systemProps.put("javax.net.ssl.trustStorePassword","passwordForTrustStore");
    System.setProperties(systemProps);
    ...

Weitere Informationen finden Sie unter Details zu RedHat Site .

12
Vic

(Umbuchung von meiner anderen Antwort )
Verwenden Sie das cli-Dienstprogramm keytool aus der Java-Softwareverteilung zum Importieren (und trust!) Der erforderlichen Zertifikate

Probe: 

  1. Wechseln Sie von cli zu jre\bin

  2. Überprüfen Sie den Keystore (Datei im Verzeichnis jre\bin).
    keytool -list -keystore ..\lib\security\cacerts
    Passwort ist changeit 

  3. Laden Sie alle Zertifikate in der Kette vom benötigten Server herunter und speichern Sie sie.

  4. Fügen Sie Zertifikate hinzu (bevor Sie das Attribut "Schreibgeschützt" in der Datei "..\lib\security\cacerts" entfernen müssen), und führen Sie Folgendes aus: .__ "r:\root.crt"

ich habe aus Versehen einen so einfachen Tipp gefunden. Andere Lösungen erfordern die Verwendung von InstallCert.Java und JDK

source: http://www.Java-samples.com/showtutorial.php?tutorialid=210

Ich hatte das gleiche Problem mit sbt.
Es wurde versucht, Abhängigkeiten von repo1.maven.org über ssl abzurufen
sagte jedoch, es sei "kein gültiger Zertifizierungspfad für angeforderte Ziel-URL gefunden".
Also folgte ich diesem Beitrag und konnte immer noch keine Verbindung überprüfen.
Also habe ich darüber gelesen und festgestellt, dass das Wurzelzertifikat nicht ausreicht, wie von der Post vorgeschlagen wurde. 
Das, was für mich funktionierte, war das Importieren der CA-Zwischenzertifikate in den Schlüsselspeicher.
Ich habe tatsächlich alle Zertifikate in der Kette hinzugefügt und es hat wie ein Zauber funktioniert.

3
Danny Mor

Lösung bei der Migration von JDK 8 auf JDK 10

JDK 10

[email protected]:/opt/jdk-minimal/jre/lib/security #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: Sun

Your keystore contains 80 entries

JDK 8

[email protected]:/usr/lib/jvm/Java-8-openjdk-AMD64/jre/lib/security/cacerts #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: Sun

Your keystore contains 151 entries

Schritte zu beheben

  • Ich habe das JDK 10-Zertifikat gelöscht und durch das JDK 8 ersetzt
  • Da ich Docker Images baue, könnte ich dies schnell mit mehrstufigen Builds tun
    • Ich baue eine minimale JRE mit jlink als /opt/jdk/bin/jlink \ --module-path /opt/jdk/jmods....

Hier sind die verschiedenen Pfade und die Reihenfolge der Befehle ...

# Java 8
COPY --from=marcellodesales-springboot-builder-jdk8 /usr/lib/jvm/Java-8-openjdk-AMD64/jre/lib/security/cacerts /etc/ssl/certs/Java/cacerts

# Java 10
RUN rm -f /opt/jdk-minimal/jre/lib/security/cacerts
RUN ln -s /etc/ssl/certs/Java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts
2

Ich arbeite an einem Tutorial für REST - Webdienste auf www.udemy.com (REST Java Web Services). Das Beispiel in diesem Lernprogramm besagte, dass für SSL ein Ordner mit dem Namen "trust_store" in meinem Eclipse- "Client" -Projekt vorhanden sein muss, das eine "Schlüsselspeicher" -Datei enthalten sollte (wir hatten ein "Client" -Projekt, um den Dienst aufzurufen und "Dienst" -Projekt, das die REST - Webdienst - 2-Projekte im selben Eclipse-Arbeitsbereich enthielt (einer ist der Client, der andere der Dienst). Um es einfach zu halten, sagten sie, dass sie "keystore.jks" vom glassfish-App-Server (glassfish\domains\domain1\config\keystore.jsk), den wir verwenden, kopieren und in diesen "trust_store" -Ordner packen, in dem sie mich gemacht haben das Kundenprojekt. Das scheint sinnvoll zu sein: Die selbst signierten Zertifikate im key_store des Servers würden den Zertifikaten im Client trust_store entsprechen. Nun habe ich den Fehler erhalten, den der ursprüngliche Beitrag erwähnt. Ich habe dies gegoogelt und gelesen, dass der Fehler auf die Datei "keystore.jks" auf dem Client zurückzuführen ist, die kein vertrauenswürdiges/signiertes Zertifikat enthält und dass das gefundene Zertifikat selbstsigniert ist.

Um die Dinge klar zu halten, lassen Sie mich sagen, dass "keystore.jsk" nach meinem Verständnis selbst signierte Zertifikate enthält und die Datei "cacerts.jks" CA-Zertifikate (von der CA signiert) enthält. "Keystore.jks" ist der "Keystore" und "cacerts.jks" ist der "Trust Store". Wie "Bruno", ein Kommentator, sagt oben, "keystore.jks" ist lokal und "cacerts.jks" für entfernte Clients.

Ich sagte mir, hey, glassfish hat auch die "cacerts.jks" -Datei, welche die trust_store-Datei von glassfish ist. cacerts.jsk soll CA-Zertifikate enthalten. Und anscheinend brauche ich im Ordner trust_store eine Schlüsselspeicherdatei, die mindestens ein CA-Zertifikat enthält. Also habe ich versucht, die Datei "cacerts.jks" in den Ordner "trust_store", den ich in meinem Kundenprojekt erstellt hatte, zu platzieren und die Eigenschaften von VM so zu ändern, dass sie auf "cacerts.jks" statt "keystore.jks" zeigt ". Das hat den Fehler beseitigt. Ich denke, es brauchte nur ein CA-Zertifikat, um zu funktionieren. 

Dies ist möglicherweise nicht ideal für die Produktion oder sogar für die Entwicklung, wenn nicht nur etwas zum Arbeiten benötigt wird. Zum Beispiel könnten Sie möglicherweise den Befehl "keytool" verwenden, um CA-Zertifikate zur Datei "keystore.jks" im Client hinzuzufügen. Aber zumindest hoffentlich werden dadurch die möglichen Szenarien eingegrenzt, die hier vorkommen könnten, um den Fehler zu verursachen. 

ALSO: Mein Ansatz schien für den Client nützlich zu sein (Serverzertifikat wurde zum Client trust_store hinzugefügt). Es scheint, dass die obigen Kommentare zur Auflösung des ursprünglichen Posts für den Server nützlich sind (Clientzertifikat zum Server trust_store hinzugefügt). Prost.

Eclipse-Projekteinrichtung:

  • MeinClientProjekt 
  • src 
  • prüfung 
  • JRE-Systembibliothek 
  • ... 
  • trust_store
    --- cacerts.jks --- keystore.jks

Ausschnitt aus der MyClientProject.Java-Datei:

static {
  // Setup the trustStore location and password
  System.setProperty("javax.net.ssl.trustStore","trust_store/cacerts.jks");
  // comment out below line
  System.setProperty("javax.net.ssl.trustStore","trust_store/keystore.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
  //System.setProperty("javax.net.debug", "all");

  // for localhost testing only
  javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
        public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost");
        }

  });
}
1
Steve T

Mein Problem war, dass ein Cloud Access Security Broker, NetSkope, über ein Softwareupdate auf meinem Arbeitslaptop installiert wurde. Dadurch wurde die Zertifikatskette geändert, und ich konnte immer noch keine Verbindung zum Server über meinen Java-Client herstellen, nachdem ich die gesamte Kette in meinen Cacerts-Schlüsselspeicher importiert hatte. Ich habe NetSkope deaktiviert und konnte mich erfolgreich verbinden.

0
gary69

Überprüfen Sie, ob die Datei $Java_HOME/lib/security/cacerts vorhanden ist! In meinem Fall war es keine Datei, sondern ein Link zu /etc/ssl/certs/Java/cacerts. Dies war auch ein Link zu sich selbst (WAS ???). Daher kann JVM die Datei nicht finden.

Lösung: Kopieren Sie die echte cacerts-Datei (Sie können dies von einem anderen JDK) in das /etc/ssl/certs/Java/-Verzeichnis und es wird Ihr Problem lösen :)

0
0x7E1