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.

20voto

Nishant Punkte 51997

Zitat aus Keine weiteren 'unable to find valid certification path to requested target'

Wenn Sie beim Versuch, eine SSL-Verbindung zu einem Host mit JSSE zu öffnen, diese Meldung erhalten, bedeutet dies in der Regel, dass der Server ein Testzertifikat verwendet (möglicherweise mit keytool generiert) anstelle eines Zertifikats von einer bekannten kommerziellen Zertifizierungsstelle wie Verisign oder GoDaddy. Webbrowser zeigen in diesem Fall Warnmeldungen an, aber da JSSE nicht davon ausgehen kann, dass ein interaktiver Benutzer vorhanden ist, wirft es standardmäßig eine Ausnahme.

Die Validierung von Zertifikaten ist ein sehr wichtiger Teil der SSL-Sicherheit, aber ich schreibe diesen Beitrag nicht, um die Details zu erklären. Wenn Sie interessiert sind, können Sie mit dem Lesen des Wikipedia-Absatzes beginnen. Ich schreibe diesen Beitrag, um einen einfachen Weg aufzuzeigen, mit diesem Host mit dem Testzertifikat zu kommunizieren, wenn Sie wirklich möchten.

Im Grunde möchten Sie das Zertifikat des Servers dem KeyStore mit Ihren vertrauenswürdigen Zertifikaten hinzufügen.

Versuchen Sie den dort bereitgestellten Code. Es könnte helfen.

6 Stimmen

Der Teil über "Zertifikatsvalidierung ist ein sehr wichtiger Teil der SSL-Sicherheit" ist nicht unbedingt wahr. SSL gibt Ihnen zwei Zusicherungen: (1) dass Ihre Kommunikation privat ist und (2) dass Sie mit einem Server sprechen, der der NSA bekannt ist. (: -) Manchmal geht es nur um die Privatsphäre des Gesprächs, und dann ist ein selbstsigniertes Zertifikat in Ordnung. Siehe social-biz.org/2011/10/16/the-anti-ssl-conspiracy

2 Stimmen

@AgilePro SSL gibt Ihnen vier Zusicherungen: Authentifizierung, Privatsphäre, Integrität und die Möglichkeit der Autorisierung. Es gibt Ihnen keine Gewährleistung, dass Sie mit einem Server sprechen, der dem NSA bekannt ist. Sich nur um Datenschutz ohne Authentifizierung zu kümmern, ist ein Widerspruch in sich.

0 Stimmen

@EJP Stimme zu, dass Sie bei Verwendung eines Client-Zertifikats Authentifizierung erhalten können und ich nehme an, die Möglichkeit der Autorisierung ... aber die meisten Verwendungen erfolgen nicht mit einem Client-Zertifikat. Wie würden Sie den Unterschied zwischen einem "selbstsignierten" Zertifikat und einem Zertifikat einer Signierungsstelle nennen? Gewährt die Signierungsstelle "Integrität"? Mein Scherz über die NSA ist, dass alle Signierungsstellen Unabhängigkeit von allem nicht garantieren können. Nicht wirklich paranoid, aber der Punkt ist, dass Ihr Zertifikat nur so geheim ist, wie es die Signierungsstelle machen kann. Selbstsignierte können geheimer sein.

11voto

VicXj Punkte 107

Einfache Schritte, die ich befolgt habe.

Problem: Ich habe versucht, eine Verbindung zu einem Endpunkt (https://%s.blob.core.windows.net) mit einer einfachen Java-Klasse (Hauptmethode) herzustellen.

Also bekam ich das oben genannte Zertifizierungsproblem, wie in der Frage erwähnt.

Lösung:

  1. Holen Sie das Zertifikat mit einem Browser (Chrome). Geben Sie dazu Ihre Endpunkt-URL in den Browser ein und drücken Sie Enter. Jetzt sehen Sie ein Schlosssymbol, klicken Sie darauf --> Zertifikat --> Details --> in Datei kopieren --> herunterladen.

  2. Öffnen Sie die Eingabeaufforderung (ich benutze Windows) als Administrator und navigieren Sie zum Verzeichnis, in dem Sie die .cer-Datei heruntergeladen haben.

3.(Optional)Wenn Sie mehrere JDK auf demselben Rechner verwenden, ändern Sie die JDK-Version so, wie Sie sie in Ihrer Anwendung verwenden.

  1. Führen Sie jetzt den folgenden Befehl aus

keytool -import -alias mycertificate -keystore "C:\Program Files\Java\jdk-11.0.5\lib\security\cacerts" -file myurlcrt.cer

  1. Geben Sie das Standardpasswort ein: changeit

  2. Dieses Zertifikat vertrauen: ja

Und damit sind Sie fertig.

Vielen Dank!

10voto

Naveen Punkte 400

Dies hat mein Problem gelöst,

Wir müssen das Zertifikat in das lokale Java importieren. Andernfalls könnten wir die folgende Ausnahme erhalten.

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen: sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifikatspfad zum angeforderten Ziel gefunden werden
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)

SSLPOKE ist ein Tool, mit dem Sie die HTTPS-Konnektivität von Ihrem lokalen Rechner aus testen können.

Befehl zum Testen der Konnektivität:

"%JAVA_HOME%/bin/java" SSLPoke  443

    sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen:
    sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifikatspfad zum angeforderten Ziel gefunden werden
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
        at sun.security.ssl.Handshaker.process\_record(Handshaker.java:961)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
        at SSLPoke.main(SSLPoke.java:31)
    Verursacht durch: sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifikatspfad zum angeforderten Ziel gefunden werden
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
        ... 15 more

keytool -import -alias  -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file 

Dies würde zuerst zur Eingabe von "Keystore-Passwort eingeben:" auffordern. changeit ist das Standardpasswort. Und schließlich würde die Meldung "Dieses Zertifikat vertrauen? [nein]:" erscheinen. Geben Sie "ja" ein, um das Zertifikat zum Keystore hinzuzufügen.

Verifikation:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke  443
Erfolgreich verbunden

2 Stimmen

Ich habe das gemacht, aber irgendwie zeigt es immer das Fehlerprotokoll an.

7voto

Praveen Punkte 378

Nur für Windows, befolgen Sie diese Schritte:

  1. In Chrome gehen Sie zu den Einstellungen.
  2. In den Einstellungen klicken Sie auf Erweiterte Einstellungen anzeigen.
  3. Unter HTTPS/SSL klicken Sie auf Zertifikate verwalten.
  4. Ihr Zertifikat exportieren.
  5. In Windows suchen (Windows-Taste auf der Tastatur drücken) Sie nach Java.
  6. Wählen Sie die Option (Java konfigurieren), die das Java Control Panel öffnet.
  7. Wählen Sie den Sicherheitstab im Java Control Panel aus.
  8. Wählen Sie Zertifikate verwalten aus.
  9. Klicken Sie auf Importieren.
  10. Unter dem (Benutzer-)Tab auswählen und Zertifikatstyp als (Vertrauenswürdige Zertifikate) auswählen.
  11. Klicken Sie auf die Importieren-Schaltfläche und durchsuchen Sie das heruntergeladene Zertifikat und importieren Sie es.

6voto

Jonas Bergström Punkte 706

Ich konnte es nur mit Code zum Laufen bringen, d.h. ohne den keytool zu verwenden:

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test
{
    private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
    private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
    private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
    private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);

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

        SSLContext sslcontext = SSLContexts.custom()
                .useTLS()
                .loadTrustMaterial(null, new TrustStrategy()
                {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
                    {
                        return true;
                    }
                })
                .build();
        SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());

        Registry sessionStrategyRegistry = RegistryBuilder.create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", sslSessionStrategy)
                .build();

        DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
        PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
        connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
        connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SOCKET_TIMEOUT.get())
                .setConnectTimeout(CONNECT_TIMEOUT.get())
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
                .setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
                .build();

        CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
                .setSSLStrategy(sslSessionStrategy)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        httpClient.start();

        // use httpClient...
    }

    private static class AllowAll implements X509HostnameVerifier
    {
        @Override
        public void verify(String s, SSLSocket sslSocket) throws IOException
        {}

        @Override
        public void verify(String s, X509Certificate x509Certificate) throws SSLException {}

        @Override
        public void verify(String s, String[] strings, String[] strings2) throws SSLException
        {}

        @Override
        public boolean verify(String s, SSLSession sslSession)
        {
            return true;
        }
    }
}

1 Stimmen

Übrigens, ich benutze httpasyncclient:4.0.1

0 Stimmen

Ich brauchte etwas Ähnliches, @JonasBergström, deine Lösung mit SSLContext hat sehr geholfen.

18 Stimmen

Bitte beachten Sie, dass diese Lösung unsicher ist.

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