Java: sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu


250

Mam klasę, która pobierze plik z serwera https . Po uruchomieniu zwraca wiele błędów. Wygląda na to, że mam problem z certyfikatem. Czy można zignorować uwierzytelnianie klient-serwer? Jeśli tak to jak?

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 Query: " + uri.toString());

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

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nRequest successfully executed");
            } else {
                System.out.println("Request failed");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Exception: " + e.getMessage());
        }
        finally {
            System.out.println("Shutting down");
            httpclient.shutdown();
        }
        System.out.println("Done");  

    }

    static class ResponseCallback extends AsyncCharConsumer<Boolean> {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Response: " + 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] Exception: " + 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] Exception: " + e.getMessage());
            }
        }

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

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

    }
}

Błędy:

URI Query: 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 error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General 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)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
    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$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    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
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
    ... 16 more
Caused by: 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] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done

2
Pewnego razu dostałem ten błąd i skontaktowałem się z naszym zespołem ds. Bezpieczeństwa i okazało się, że muszę załatać plik JAR, którego używamy, ponieważ nasz zespół używał przestarzałego dostarczonego przez firmę. Tylko informacja dla każdego, kto może być w podobnej sytuacji.
kayleeFrye_onDeck

Odpowiedzi:


215

Problem pojawia się, gdy serwer ma samopodpisany certyfikat. Aby obejść ten problem, możesz dodać ten certyfikat do listy zaufanych certyfikatów maszyny JVM.

W tym artykule autor opisuje, jak pobrać certyfikat z przeglądarki i dodać go do pliku cacerts JVM. Możesz edytować JAVA_HOME/jre/lib/security/cacertsplik lub uruchomić aplikację z -Djavax.net.ssl.trustStoreparametrem. Sprawdź, którego JDK / JRE używasz, ponieważ często jest to źródłem zamieszania.

Zobacz także: Jak są rozwiązywane nazwy serwerów certyfikatów SSL / Czy mogę dodawać alternatywne nazwy za pomocą keytool? Jeśli spotkasz java.security.cert.CertificateException: No name matching localhost foundwyjątek.


3
to mi nie zadziałało. Mam zainstalowany katalog główny i certyfikat łańcucha, ale Tomcat-7 nadal zgłasza wyjątek walidatora spowodowany przez „niemożność znalezienia prawidłowej ścieżki certyfikacji do żądanego celu” w jakikolwiek sposób, aby to debugować?
Cheruvim,

Problem pojawia się również w przypadku certyfikatu podpisanego przez osobę, która nie jest zaufana.
Markiz Lorne

Wspaniały! To działa! Tylko nie zapomnij, że możesz mieć zarówno Jre, jak i JDK, i oba cacertsmuszą być zaktualizowane
Dima Fomin

W moim przypadku główny urząd certyfikacji już tam był, ale nie ma następnego. Dodanie kolejnego CA załatwiło sprawę - dzięki.
java-addict301

1
W moim przypadku używam Netbeans + Apache Tomcat (zintegrowany), więc dodając .cer do magazynu zaufania „cacerts” na Jdk / jre (C: \ Program Files \ Java \ jdk1.8.0_152 \ jre \ lib \ security) i Jre (C: \ Program Files \ Java \ jre1.8.0_91 \ lib \ security) działa dla mnie
Jnn

149

Oto, co niezawodnie działa dla mnie w systemie macOS. Pamiętaj, aby zastąpić example.com i 443 rzeczywistą nazwą hosta i portem, z którym próbujesz się połączyć, i podać niestandardowy alias. Pierwsze polecenie pobiera dostarczony certyfikat ze zdalnego serwera i zapisuje go lokalnie w formacie x509. Drugie polecenie ładuje zapisany certyfikat do magazynu zaufanych certyfikatów SSL 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

3
Pracuje dla mnie dlaczego? Musisz podać wyjaśnienie.
Markiz Lorne

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2> / dev / null) -out ~ / example.crt - co to jest example.crt w poleceniu mam certyfikat .pem, który muszę podać to tutaj ??
Wisznu Ranganathan

3
.crt i .pem są powszechnie używanymi rozszerzeniami plików dla tego samego formatu pliku. Jeśli masz już plik, po prostu uruchom drugie polecenie i przekaż je do argumentu -file.
Gabe Martin-Dempesy

1
Świetne rzeczy. Jedyna rzecz: musiałem użyć najnowszego openssl 1.0.Xx z jakiegoś powodu, stary 9.X.Xx nie działał.
zbstof

1
To nie działa z punktem końcowym SNI. W takim przypadku należy dodać: -servername example.com podczas pobierania certyfikatu
Patrik Beck

46

Miałem ten sam problem z ważnym podpisanym certyfikatem wieloznacznym z firmy Symantec.

Najpierw spróbuj uruchomić aplikację Java z -Djavax.net.debug = SSL, aby zobaczyć, co się naprawdę dzieje.

W końcu zaimportowałem certyfikat pośredni, który spowodował zerwanie łańcucha certyfikatów.

Pobrałem brakujący certyfikat pośredni z firmy Symantec (link do brakującego certyfikatu można zobaczyć w dzienniku uzgadniania ssl: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer w moim przypadku).

Zaimportowałem certyfikat do magazynu kluczy Java. Po zaimportowaniu certyfikatu pośredniego mój wildcard ssl cert w końcu zaczął działać:

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

Tak było w przypadku:
kisna

2
Aby uniknąć pomyłek, uruchom java (lub jcurl) z parametrami debugowania, aby zobaczyć zdalny „łańcuch certyfikatów” w logach, a następnie grep „CN” w magazynie zaufanych certyfikatów jawnie przekazany (zamiast domyślnego) w następujący sposób, jeśli nie jest obecny, musisz dodać. ssllabs.com/ssltest/analyze.html pokaże, czy certyfikaty po stronie serwera mają niepełny łańcuch, i zawiera certyfikaty pośredniej ścieżki certyfikacji, które należy dodać. -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
kisna

I oczywiście oficjalny artykuł dotyczący debugowania problemów z SSL: docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/... blogs.oracle.com/java-platform-group/entry/…
kisna

Miałem ten sam problem, jest to bardzo przydatne, ale w moim przypadku wystarczy tylko dodać certyfikat serwera do pliku cacerts wersji JDK
Pigritia

Należy pamiętać, że istnieje inne narzędzie o nazwie portecle, które może łatwo otworzyć plik Cacert (magazyn certyfikatów) i łatwo zaimportować certyfikat. Pamiętaj tylko, aby zapisać plik cacert później.
will824

41
  1. Wyeksportuj certyfikat SSL za pomocą przeglądarki Firefox. Możesz go wyeksportować, klikając adres URL w przeglądarce, a następnie wybierz opcję wyeksportowania certyfikatu. Załóżmy, że nazwa pliku cert to twoja.ssl.server.name.crt
  2. Idź do swojego JRE_HOME/binlubJDK/JRE/bin
  3. Wpisz polecenie
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Uruchom ponownie proces Java

13
Jeśli zostaniesz poproszony o hasło, użyj domyślnego hasła magazynu kluczy cacerts changeit( stackoverflow.com/a/22782035/1304830 ). Pamiętaj też, aby uruchomić cmd jako administrator.
Fr4nz

22

Odpowiedź Gabe'a Martina-Dempesy'ego jest mi pomocna. I napisałem krótki skrypt z tym związany. Użycie jest bardzo proste.

Zainstaluj certyfikat z hosta:

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

Usuń już zainstalowany certyfikat.

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

java-cert-importer.sh

#!/usr/bin/env bash

# Exit on error
set -e

# Ensure script is running as root
if [ "$EUID" -ne 0 ]
  then echo "WARN: Please run as root (sudo)"
  exit 1
fi

# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }

# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)

usage:  ./java-cert-importer.sh <host> [ <port> | default=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 "WARN: Java home cannot be found."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARN: Detected Java home does not exists: $javahome"
    exit 1
fi

echo "Detected Java Home: $javahome"

# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Certificate is deleted for ${host}"
    exit 0
fi

# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port

# create temp file
tmpfile="/tmp/${host}.$$.crt"

# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts Backup: ${cacertsbackup}"

# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Remove temp certificate file
rm ${tmpfile}

# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")

# Show results to user
if [ "$result" ]; then
    echo "Success: Certificate is imported to java cacerts for ${host}";
else
    echo "Error: Something went wrong";
fi;

Działa bezbłędnie. Dobra robota! . Oto jak to działa: uruchom usługę SSL (jeśli nie jest uruchomiona) i wykonaj polecenie zgodnie z wyjaśnieniem (np ./java-cert-importer.sh example.com 1234.). Otóż ​​to.
Lepe

1
Działa świetnie. Pojawił się błąd na serwerze Jenkins łączącym się z zewnętrznym interfejsem API, który zmienia jego certyfikat i nie udaje się zbudować mojego systemu. To rozwiązuje mój problem
user9869932,

Oracle powinien był przede wszystkim dostarczyć coś takiego, bo nigdy nie stworzył własnego okropnego rozwiązania SSL. Obsługa certyfikatów SSL powinna być zadaniem systemu operacyjnego.
Wolfgang Fahl

17

Cytowanie z „Nie można już znaleźć prawidłowej ścieżki certyfikacji do żądanego celu”

podczas próby otwarcia połączenia SSL z hostem za pomocą JSSE. Zazwyczaj oznacza to, że serwer używa certyfikatu testowego (ewentualnie wygenerowanego za pomocą keytool), a nie certyfikatu znanego komercyjnego urzędu certyfikacji, takiego jak Verisign lub GoDaddy. Przeglądarki internetowe wyświetlają w tym przypadku okna dialogowe z ostrzeżeniami, ale ponieważ JSSE nie może zakładać, że użytkownik interaktywny jest obecny, domyślnie zgłasza wyjątek.

Sprawdzanie poprawności certyfikatu jest bardzo ważną częścią bezpieczeństwa SSL, ale nie piszę tego wpisu, aby wyjaśnić szczegóły. Jeśli jesteś zainteresowany, możesz zacząć od przeczytania Wikipedii. Piszę ten wpis, aby pokazać prosty sposób rozmowy z tym hostem za pomocą certyfikatu testowego, jeśli naprawdę tego chcesz.

Zasadniczo chcesz dodać certyfikat serwera do magazynu kluczy za pomocą zaufanych certyfikatów

Wypróbuj kod tam podany. To może pomóc.


5
Część „Sprawdzanie poprawności certyfikatu jest bardzo ważną częścią bezpieczeństwa SSL” niekoniecznie musi być prawdziwa. SSL zapewnia dwie gwarancje: (1) że twoja komunikacja jest prywatna i (2) rozmawiasz z serwerem znanym NSA. (:-) Czasami zależy ci tylko na prywatności rozmowy, a następnie certyfikat z podpisem własnym jest w porządku. Zobacz social-biz.org/2011/10/16/the-anti-ssl-conspiracy
AgilePro

@AgilePro SSL zapewnia cztery gwarancje: uwierzytelnianie, prywatność, integralność i możliwość autoryzacji. To nie nie daje żadnych gwarancji, że mówisz do serwera znanego NSA. Dbanie tylko o prywatność bez uwierzytelniania jest sprzecznością.
Markiz Lorne

@EJP Zgadzam się, że jeśli używasz certyfikatu klienta, możesz uzyskać uwierzytelnienie, i przypuszczam, że istnieje możliwość autoryzacji ... ale większość zastosowań nie dotyczy certyfikatu klienta. Jak nazwałbyś różnicę między certyfikatem „samopodpisanym” a certyfikatem organu podpisującego? Czy organ podpisujący zapewnia „integralność”. Żartuję z NSA, że wszystkie organy podpisujące nie mogą pozytywnie zagwarantować niezależności od wszystkiego. Nie do końca paranoik, ale chodzi o to, że twój certyfikat jest TYLKO tak tajny, jak tylko może to zrobić organ podpisujący. Samopodpisane mogą być bardziej tajne.
AgilePro

@AgilePro Użycie certyfikatu serwera uwierzytelnia serwer i jest wymagane do zapewnienia bezpieczeństwa SSL, jak zaznaczono w RFC 2246. Certyfikaty wcale nie są tajne: dlatego pozostała część komentarza nie ma sensu.
Markiz Lorne

6

To rozwiązało mój problem,

Musimy zaimportować certyfikat do lokalnej Java. Jeśli nie, możemy uzyskać poniższy wyjątek.

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: Budowanie ścieżki PKIX nie powiodło się: sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu
        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 to narzędzie, w którym można przetestować łączność https z lokalnego komputera.

Polecenie przetestowania łączności:

"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
    sun.security.validator.ValidatorException: Budowanie ścieżki PKIX nie powiodło się: 
    sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu
        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)
    Przyczyna: sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do 
    żądany cel
        w 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 więcej
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>

najpierw wyświetli się monit „Wprowadź hasło magazynu kluczy:” changeitto hasło domyślne. i na koniec monit „Zaufaj temu certyfikatowi [[nie]:”), wpisz „tak”, aby dodać certyfikat do magazynu kluczy.

Weryfikacja:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    

5

Udało mi się sprawić, że działa tylko z kodem, tzn. Nie trzeba używać keytoola:

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<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>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
Btw, używam httpasyncclient: 4.0.1
Jonas Bergström

Potrzebowałem czegoś podobnego, @ JonasBergström, twoje rozwiązanie z SSLContext bardzo pomaga.
EnterSB

8
Pamiętaj, że to rozwiązanie jest niepewne.
Markiz Lorne

Dziękuję Jonas, twoje rozwiązanie rozwiązało problem. Ale okazało się, że utworzenie pierwszego połączenia kosztuje bardzo długo (3–5 sekund), a potem każde połączenie potrzebuje tylko 300–400 ms.
twcai

5

Źródłem tego błędu w mojej instancji Apache 2.4 (przy użyciu certyfikatu wieloznacznego Comodo) była niekompletna ścieżka do podpisanego certyfikatu głównego SHA-1. W wydanym certyfikacie było wiele łańcuchów, aw łańcuchu prowadzącym do certyfikatu głównego SHA-1 brakowało certyfikatu pośredniego . Nowoczesne przeglądarki wiedzą, jak sobie z tym poradzić, ale Java 7 domyślnie tego nie obsługuje (chociaż istnieją pewne skomplikowane sposoby osiągnięcia tego w kodzie). Rezultatem są komunikaty o błędach wyglądające identycznie jak w przypadku certyfikatów z podpisem własnym:

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
    ... 22 more

W takim przypadku pojawia się komunikat „nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu” z powodu braku certyfikatu pośredniego. Możesz sprawdzić, którego certyfikatu brakuje, testując SSL Labs na serwerze. Po znalezieniu odpowiedniego certyfikatu pobierz go i (jeśli serwer jest pod twoją kontrolą) dodaj go do pakietu certyfikatów. Możesz też zaimportować brakujący certyfikat lokalnie. Uwzględnienie tego problemu na serwerze jest bardziej ogólnym rozwiązaniem problemu.


ssllabs.com/ssltest jest wybawcą, wystarczy porównać go z działającym sprawdzeniem poprawności certyfikatu.
kisna

5

Tylko w systemie Windows wykonaj następujące kroki:

  1. W Chrome przejdź do ustawień.
  2. W Ustawieniach kliknij pokaż ustawienia zaawansowane.
  3. W obszarze HTTPS / SSL kliknij Zarządzaj certyfikatami.
  4. Wyeksportuj swój certyfikat.
  5. W wyszukiwaniu w systemie Windows (naciskając klawisz Windows na klawiaturze) wpisz java.
  6. Wybierz opcję (Konfiguruj Java), która otworzy Panel sterowania Java
  7. Wybierz kartę Zabezpieczenia w Panelu sterowania Java
  8. Wybierz Zarządzaj certyfikatami
  9. Kliknij opcję Importuj
  10. W zakładce (Użytkownik) wybrano i typ certyfikatu jako (Zaufane certyfikaty)
  11. Kliknij przycisk importuj, przejdź do pobranego certyfikatu i zaimportuj go.

4

Dla tych, którzy lubią Debian i paczkowaną Javę:

sudo mkdir /usr/share/ca-certificates/test/  # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates  # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose

Nie zapomnij sprawdzić /etc/default/cacerts:

# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes

Aby usunąć cert:

sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose

2

Może to być również spowodowane używaniem certyfikatów GoDaddy w Javie 7 podpisanych przy użyciu SHA2.

Chrome i wszystkie inne przeglądarki zaczynają tracić ważność certyfikatów SSL podpisanych przy użyciu SHA1, ponieważ nie jest to tak bezpieczne.

Więcej informacji na temat problemu można znaleźć tutaj , a także, w jaki sposób rozwiązać go na serwerze, jeśli jest to konieczne.


2

Miałem ten sam problem z błędem certyfikatów i byłem z powodu SNI, a klient HTTP, którego użyłem, nie miał zaimplementowanego SNI. Tak więc aktualizacja wersji wykonała zadanie

   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>

2

AKTUALIZACJA: To, że ponowne uruchomienie pomogło, było przypadkowe (miałem nadzieję, hura!). Prawdziwa przyczyna problemu była następująca: gdy Gradle otrzymuje polecenie użycia określonego magazynu kluczy, ten magazyn kluczy musi również zawierać wszystkie oficjalne certyfikaty główne. W przeciwnym razie nie może uzyskać dostępu do bibliotek ze zwykłych repozytoriów. Musiałem to zrobić:

Zaimportuj samopodpisany certyfikat:

keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks

Dodaj oficjalne certyfikaty główne:

keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks

Może przeszkadzał też demon Gradle. Być może warto zabić wszystkie uruchomione demony, ./gradlew --statusjeśli wszystko zacznie wyglądać ponuro.

ORYGINALNE OGŁOSZENIE:

Wiem, że nikt w to nie uwierzy. Mimo to, jeśli wszystko inne zawiedzie, spróbuj: Po ponownym uruchomieniu komputera Mac problem zniknął. Grrr.

Tło: słoik ./gradlew ciągle daje mi „nie mogę znaleźć ważnej ścieżki certyfikacji do żądanego celu”

Utknąłem z samopodpisanym certyfikatem, zapisanym z przeglądarki, zaimportowanym do privateKeystore.jks. Następnie poinstruował Gradle, aby współpracował z privateKeystore.jks:

org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit

Jak wspomniano, działało to dopiero po ponownym uruchomieniu.


2

AVG w wersji 18.1.3044 (z Windows 10) zakłóca moją lokalną aplikację Spring.

Rozwiązanie: wpisz sekcję AVG o nazwie „Internet i poczta e-mail” i wyłącz „ochronę poczty e-mail”. AVG blokuje certyfikat, jeśli witryna nie jest bezpieczna.



2

Jest wiele sposobów na rozwiązanie tego ...

Jednym ze sposobów jest ustawienie certyfikatów TrustStore w pliku kluczy i umieszczenie go w ścieżce aplikacji oraz ustawienie tych właściwości systemowych w głównej metodzie:

public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}

Innym sposobem jest umieszczenie magazynu kluczy jako pliku zasobów w pliku jar projektu i załadowanie go:

public static SSLContext createSSLContext(String resourcePath, String pass) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException {
  // initialise the keystore
  final char[] password = pass.toCharArray();
  KeyStore ks = KeyStore.getInstance("JKS");
  ks.load(ThisClass.class.getResourceAsStream(resourcePath
  ), password);

  // Setup the key manager factory.
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(ks, password);

  // Setup the trust manager factory.
  TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  tmf.init(ks);

  SSLContext sslc = SSLContext.getInstance("TLS");
  sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  return sslc;
}

public static void main(String[] args) {
  SSLContext.setDefault(
    createSSLContext("/trust-store.jks", "TrustStore"));
  ...
}

W systemie Windows możesz również wypróbować to rozwiązanie: https://stackoverflow.com/a/59056537/980442


Plik magazynu kluczy utworzyłem z pliku CA urzędu certyfikacji .crtw następujący sposób:

keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt

FYI: https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html


1

Masz dwie opcje: zaimportuj samopodpisany certyfikat do magazynu kluczy Java dla każdego pliku JVM, na którym będzie działać oprogramowanie, lub wypróbuj nie sprawdzającą fabrykę ssl:

jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

1

Miałem problem taki jak ten obraz.

wprowadź opis zdjęcia tutaj

Wypróbowałem kilka rozwiązań. Ale okazało się, że nawet jeśli jest to ten sam projekt, gdy jest w miejscu pracy drugiego, jest całkowicie w porządku. Nie są wymagane żadne dodatkowe ustawienia. Więc zgadliśmy, że jest to problem środowiskowy. Próbowaliśmy zmienić wersję JDK, IDE, ale nie działało. dochodzenie zajęło około 4 godzin, zanim wypróbowaliśmy najlepiej ocenianą odpowiedź. Nie znalazłem błędu wspomnianego w tej odpowiedzi, ale znalazłem za pośrednictwem przeglądarki HTTP URL (blokada), że istnieje certyfikat Charlesa. Potem zdałem sobie sprawę, że mój Charles był cały czas włączony. Tak długo, jak to wyłączyłem, wszystko działa dobrze.

Opuściłem więc moje doświadczenie, które może być pomocne w twojej sprawie.


0

W moim przypadku używam MacOs High Sierra z Javą 1.6. Plik cacert znajduje się w innym miejscu niż wspomniane powyżej w odpowiedzi Gabe Martin-Dempesy. Plik cacert był już również powiązany z inną lokalizacją (/ Library / Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts).

Za pomocą FireFox wyeksportowałem certyfikat z omawianej strony internetowej do lokalnego pliku o nazwie „exportedCertFile.crt”. Stamtąd użyłem keytool do przeniesienia certyfikatu do pliku cacert. To rozwiązało problem.

bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit

0

najpierw pobierz certyfikat ssl, a następnie przejdź do ścieżki bin Java, wykonaj poniższe polecenie w konsoli.

C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore

-1

W moim przypadku zarówno magazyn kluczy, jak i magazyn zaufanych certyfikatów posiadały ten sam certyfikat, więc usunięcie zaufanego magazynu pomogło. Czasami łańcuch certyfikatów może być problemem, jeśli masz wiele kopii certyfikatów.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.