Rozwiązywanie problemu javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: kompilacja ścieżki PKIX nie powiodła się Błąd?


426

Edycja: - Próbowałem sformatować pytanie i zaakceptowałem odpowiedź w bardziej reprezentatywny sposób na moim blogu

Oto oryginalny numer.

Otrzymuję ten błąd:

szczegółowy komunikat sun.security.validator.ValidatorException: Kompilacja ścieżki PKIX nie powiodła się:
sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu

powoduje javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: nie powiodło się budowanie ścieżki PKIX: sun.security.provider.certpath.SunCertPathBuilderException: nie można znaleźć prawidłowej ścieżki certyfikacji do żądanego celu

Używam Tomcat 6 jako serwera WWW. Mam dwie aplikacje internetowe HTTPS zainstalowane na różnych Tomcats na różnych portach, ale na tym samym komputerze. Powiedz App1(port 8443)i App2(port 443). App1łączy się z App2. Po App1nawiązaniu połączenia App2otrzymuję powyższy błąd. Wiem, że jest to bardzo częsty błąd, więc natknąłem się na wiele rozwiązań na różnych forach i stronach. Mam poniższy wpis w server.xmlobu Tomcats:

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

Każda witryna podaje ten sam powód, dla którego certyfikat podany przez app2 nie znajduje się w zaufanym magazynie jvm app1. Wydaje się, że tak jest również wtedy, gdy próbowałem trafić w ten sam adres URL w przeglądarce IE, działa (działa z ociepleniem, jest problem z certyfikatem bezpieczeństwa tej strony. Tutaj mówię, kontynuuj na tej stronie). Ale kiedy klient Java uderza w ten sam adres URL (w moim przypadku), pojawia się powyższy błąd. Aby umieścić go w magazynie zaufania, wypróbowałem trzy opcje:

Opcja 1

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

Opcja 2 Ustawienie poniżej w zmiennej środowiskowej

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

Opcja 3 Ustawienie poniżej w zmiennej środowiskowej

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

Ale nic nie działało .

Co w końcu działało, stosując podejście Java sugerowane w Jak obsługiwać nieprawidłowe certyfikaty SSL za pomocą Apache HttpClient? przez Pascal Thivent, tj. wykonując program InstallCert.

Ale takie podejście jest dobre dla konfiguracji devboksa, ale nie mogę go używać w środowisku produkcyjnym.

Zastanawiam się dlaczego trzema podejściami wymienionymi powyżej nie działa, gdy wspomniałem te same wartości server.xmlod app2wartości serwerowych i samych w truststore przez ustawienie

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

w app1programie.

Aby uzyskać więcej informacji, w ten sposób nawiązuję połączenie:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();

  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());

możliwy duplikat HttpClient i SSL
markiz Lorne

O dziwo, dostałem ten błąd podczas komunikacji między serwerami klastrowymi, które indywidualnie nie miały problemów z SSL. Po prawidłowym ustawieniu domainnameserwerów RHEL problem zniknął. Mam nadzieję, że to komuś pomoże.
DavidG

Jeszcze jedną rzeczą do sprawdzenia jest to, że masz najnowszą wersję Java - otrzymałem podobny błąd z tego powodu.
Redzarf

stackoverflow.com/questions/2893819/… - również trafne i fantastyczna odpowiedź.
Siddhartha,

Odpowiedzi:


406

Musisz dodać certyfikat dla App2 do pliku zaufanych certyfikatów używanej maszyny JVM znajdującej się pod adresem %JAVA_HOME%\lib\security\cacerts.

Najpierw możesz sprawdzić, czy certyfikat znajduje się już w magazynie zaufania, uruchamiając następującą komendę: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts"(nie musisz podawać hasła)

Jeśli brakuje certyfikatu, możesz go uzyskać, pobierając go za pomocą przeglądarki i dodając go do magazynu zaufanych certyfikatów za pomocą następującego polecenia:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

Po zaimportowaniu możesz ponownie uruchomić pierwsze polecenie, aby sprawdzić, czy certyfikat został dodany.

Informacje o Sun / Oracle można znaleźć tutaj .


6
Musisz użyć pełnej ścieżki, np. C: \ java \ jdk \ lib \ security \ cacerts
SimonSez

48
Jak powiedział SimonSez, nie potrzebujesz hasła, ale jeśli chcesz, domyślnym hasłem jest „zmień”.
Felix

16
Ponadto w systemie Windows musisz uruchomić terminal jako administrator, w przeciwnym razie wystąpi błąd keytool error: java.io.FileNotFoundException ... (Access is denied)podczas próby zaimportowania certyfikatu.
Felix

2
Ach @SimonSez jesteś moim bogiem. Ale aby go dodać, należy podać lokalizację magazynu zaufanych certyfikatów i hasło, jak wspomniano w @M Sach, aby działało.
BudsNanKis

2
Nadal występują problemy z Javą 1.8. Konieczne było dodanie certyfikatu zgodnie z opisem i użycie Java <1.8
Tom Howard

180

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

• Gdy otrzymałem błąd, próbowałem wyjawić znaczenie wyrażenia przez Google i stwierdziłem, że ten problem występuje, gdy serwer zmienia certyfikat SSL HTTPS, a nasza starsza wersja java nie rozpoznaje głównego ośrodka certyfikacji (CA) .

• Jeśli masz dostęp do adresu URL HTTPS w przeglądarce, możesz zaktualizować Javę, aby rozpoznała główny urząd certyfikacji.

• W przeglądarce przejdź do adresu URL HTTPS, do którego Java nie mogła uzyskać dostępu. Kliknij łańcuch certyfikatów HTTPS (w przeglądarce Internet Explorer znajduje się ikona kłódki), kliknij blokadę, aby wyświetlić certyfikat.

• Przejdź do „Szczegóły” certyfikatu i „Kopiuj do pliku”. Skopiuj go w formacie Base64 (.cer) . Zostanie zapisany na pulpicie.

• Zainstaluj certyfikat, ignorując wszystkie alerty.

• W ten sposób zebrałem informacje o certyfikacie adresu URL, do którego próbowałem uzyskać dostęp.

Teraz musiałem sprawić, aby moja wersja java wiedziała o certyfikacie, aby dalej nie odmawiał rozpoznania adresu URL. W związku z tym muszę wspomnieć, że wylogowałem się, że informacje o certyfikacie głównym pozostają domyślnie w lokalizacji JDK \ jre \ lib \ security , a domyślne hasło dostępu to: changeit.

Aby wyświetlić informacje o cacertach, należy postępować zgodnie z następującymi procedurami:

• Kliknij przycisk Start -> Uruchom

• Wpisz cmd. Wiersz polecenia zostanie otwarty (może być konieczne otwarcie go jako administratora).

• Przejdź do swojego Java/jreX/binkatalogu

• Wpisz następujące polecenie

keytool -list -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

Podaje listę bieżących certyfikatów zawartych w magazynie kluczy. Wygląda to mniej więcej tak:

C: \ Documents and Settings \ NeelanjanaG> keytool -list -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

Wprowadź hasło do magazynu kluczy: zmień

Typ magazynu kluczy: jks

Dostawca kluczy: SUN

Twój magazyn kluczy zawiera 44 wpisy

verisignclass3g2ca, 26 marca 2004 r., trustCertEntry,

Odcisk palca certyfikatu (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9

entrustclientca, 9 stycznia 2003, trustCertEntry,

Odcisk palca certyfikatu (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4

thawtepersonalbasicca, 13 lutego 1999, zaufanyCertEntry,

Odcisk palca certyfikatu (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41

addtrustclass1ca, 1 maja 2006, trustCertEntry,

Odcisk palca certyfikatu (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC

verisignclass2g3ca, 26 marca 2004 r., trustCertEntry,

Odcisk palca certyfikatu (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6

• Teraz musiałem dołączyć wcześniej zainstalowany certyfikat do cacerts.

• W tym celu procedura jest następująca:

keytool –import –noprompt –trustcacerts –alias ALIASNAME -plik FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD

Jeśli używasz Java 7:

keytool –importcert –trustcacerts –alias ALIASNAME -plik PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

• Następnie doda informacje o certyfikacie do pliku cacert.

To rozwiązanie znalazłem dla wyżej wspomnianego wyjątku !!


5
Co robisz po wygaśnięciu certyfikatu? Powtórz wszystko (raz w roku)?
ggkmath

7
Czy jest jakiś sposób to zrobić programowo?
Meshulam Silk

1
Dla osób zajmujących się błędem PKIX „Ścieżka nie łączy się z żadną kotwicą zaufania”, to rozwiązanie niestety nie rozwiązało tego problemu.
IcedDante

3
Jedno pytanie - czy aliasName to adres internetowy, dla którego importujemy certyfikat? Na przykład, jeśli URL to domain.site.com/pages/service.asmx, to powinien być alias domain.site.com lub pełny adres URL (domain.site.com/pages/service.asmx) lub powinien być również poprzedzony http : // czy to tylko dowolna nazwa?
nanosoft

1
ścieżka: \ lib \ security> keytool -import -noprompt -trustcacerts -alias webCert -plik webCertResource.cer -keystore c: / Users / Jackie / Desktop -storepass changeit Otrzymuję „system nie może znaleźć określonego pliku”
Jesse

46

Jak to zrobić w Tomcat 7

Chciałem obsługiwać samopodpisany certyfikat w aplikacji Tomcat, ale następujący fragment kodu nie działa

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

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

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "{}";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    }
}

oto, co rozwiązało mój problem:

1) Pobierz .crtplik

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • zamień na <your domain>swoją domenę (np. jossef.com)

2) Zastosuj .crtplik w cacertsmagazynie certyfikatów Java

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
  • zamień na <your domain>swoją domenę (np. jossef.com)
  • zamień na <JAVA HOME>swój katalog domowy java

3) Włam się

Mimo że iv zainstalowałem mój certyfikat w Javadomyślnych magazynach certyfikatów, Tomcat ignoruje to (wygląda na to, że nie jest skonfigurowane do używania domyślnych magazynów certyfikatów Javy).

Aby zhakować to, dodaj gdzieś w kodzie:

String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...

4
Krok 2 wykonał dla mnie sztuczkę za pomocą SpringBoot i Tomcat 7. Dziękuję.
Tim Perry,

Czy muszę korzystać z keytool z java, z którego korzysta tomcat? Ponieważ na jednym serwerze mogę mieć wiele java
vikifor

@vikifor tak. Możesz także uruchomić go dla wszystkich katalogów Java zainstalowanych w twoim systemie
Jossef Harush

1
To zadziałało! dzięki tonie @JossefHarush za tak przydatną odpowiedź!
Tom Taylor

1
mój problem został rozwiązany po dodaniu segmentu kodu @Jossefa Harusha do mojego kodu.
Chamod Pathirana

10

W moim przypadku problem polegał na tym, że serwer WWW wysyłał tylko certyfikat i pośredni urząd certyfikacji, a nie główny urząd certyfikacji. Dodanie tej opcji JVM rozwiązało problem:-Dcom.sun.security.enableAIAcaIssuers=true

Dostępna jest obsługa metody dostępu do usługi CAIssuers dla rozszerzenia Access Information Authority. Jest on domyślnie wyłączony ze względu na kompatybilność i można go włączyć, ustawiając właściwość systemową com.sun.security.enableAIAcaIssuersna wartość true.

Jeśli ustawiona na wartość true, implementacja PKIX firmy Sun przez CertPathBuilder wykorzystuje informacje z rozszerzenia AIA certyfikatu (oprócz określonych CertStores) do znalezienia wystawiającego certyfikatu CA, pod warunkiem, że jest to identyfikator URI typu ldap, http lub ftp.

Źródło


To faktycznie rozwiązało mój problem, dzięki!
Luís Silva,

6

Innym powodem może być przestarzała wersja JDK. Używałem jdk w wersji 1.8.0_60, po prostu aktualizacja do najnowszej wersji rozwiązała problem z certyfikatem.


2
Też miałem ten sam problem. Wywołanie interfejsu API z certyfikatem Lets Encrypt może nie działać ze starszymi wersjami Java, ponieważ nie jest rozpoznawany przez zaufane główne urzędy certyfikacji. Aktualizacja oprogramowania Java rozwiąże ten problem.
hertg

5

Mój plik cacerts był całkowicie pusty. Rozwiązałem to, kopiując plik cacerts z mojego komputera z systemem Windows (który używa Oracle Java 7) i scpded go do mojego Linux-a (OpenJDK).

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

a następnie na maszynie z Linuksem

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

Do tej pory działało świetnie.


1
Działa to wspaniale, jeśli problem polega na tym, że używasz starszej wersji Java, która nie ma najnowszych certyfikatów.
atripathi

@atripathi co powiesz na komputer Mac?
iOSAndroidWindowsMobileAppsDev

Wystąpił poważny błąd w instalacji Java, jeśli plik cacerts był pusty. Powinieneś był zainstalować to wszystko ponownie.
Markiz Lorne

Być może, ale to rozwiązanie zadziałało i nic potem nie było złe.
Ryan Shillington

5

Dla mnie ten błąd pojawił się również podczas próby połączenia się z procesem za odwrotnym proxy NGINX, który obsługiwał SSL.

Okazało się, że problemem był certyfikat bez powiązania całego łańcucha certyfikatów. Kiedy dodałem pośrednie certyfikaty, problem został rozwiązany.

Mam nadzieję że to pomoże.


to wygląda na to, co mam. czy możesz wyjaśnić, w jaki sposób dodałeś pośrednie certyfikaty i gdzie. używam serwera proxy httpd revers, a nie NGINX.
Asaf Magen

pomogło mi to w moim przypadku, ponieważ korzystam z httpd: access.redhat.com/solutions/43575
Asaf Magen

W przypadku nginx używa tylko plików .key i .pem do konfiguracji SSL. Najpierw konwertujesz .crt na .pem (po prostu: cp twój_plik.crt twój_plik.pem), a następnie dla łańcucha certyfikatów SSL: dołączasz plik .cer do ostatniego pliku .pem (cat twój_plik.cer >> twój_plik.pem)
Thế Anh Nguyễn

5

Używając Tomcat 7 pod Linuksem, załatwiło sprawę.

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Pod Linuksem $JAVA_HOMEnie zawsze jest konfigurowany, ale zwykle /etc/alternatives/jrewskazuje$JAVA_HOME/jre


5

Poniższy kod działa dla mnie:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TrustAnyTrustManager implements X509TrustManager {

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

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}

HttpsURLConnection conn = null;
            URL url = new URL(serviceUrl);
            conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());  

             conn.setSSLSocketFactory(sc.getSocketFactory());

5
Ten kod jest całkowicie niepewny i nie należy go używać.
Markiz Lorne

@ user207421 Dlaczego to nie jest bezpieczne? Co krótko dzieje się w kodzie?
Govinda Sakhare

Pomija to sprawdzanie poprawności certyfikatów, w zasadzie pozwala na zaakceptowanie dowolnego certyfikatu. Sposób działania certyfikatów polega na tym, że istnieje certyfikat fizyczny (dosłownie) fizycznie chroniony w różnych urzędach certyfikujących. Ten certyfikat jest następnie wykorzystywany do wydawania innych certyfikatów dodatkowych, które można zweryfikować aż do głównego urzędu certyfikacji. Pomija to wszystkie wcześniejsze kontrole, co oznacza, że ​​mogę wysłać dowolny certyfikat ssl (nawet wygenerowany samodzielnie), a twoja aplikacja zaakceptuje go tak bezpiecznie, nawet jeśli moja tożsamość jako URL nie jest zweryfikowana.
Scott Taylor

4

Korzystałem jdk1.8.0_171z tego samego problemu. Próbowałem tutaj 2 najlepszych rozwiązań (dodawanie certyfikatu za pomocą keytool i innego rozwiązania, które zawiera hack), ale one nie działały dla mnie.

Zaktualizowałem mój JDK do 1.8.0_181i działało to jak urok.


2

napisałem mały, głupi skrypt cmd (wiersz poleceń) Win32 (WinXP 32bit testet), który wyszukuje wszystkie wersje Java w plikach programu i dodaje do nich certyfikat. Hasło musi być domyślnym „changeit” lub zmienić je samodzielnie w skrypcie :-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause

2

Dla MacOS X poniżej znajduje się dokładne polecenie, które działało dla mnie, gdzie musiałem spróbować z podwójnym łącznikiem w opcji „importcert”, która działała:

sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit

2

Dla mnie nie działa rozpoznane rozwiązanie z tego postu: https://stackoverflow.com/a/9619478/4507034 .

Zamiast tego udało mi się rozwiązać problem, importując certyfikat do zaufanych certyfikatów mojego komputera.

Kroki:

  1. Przejdź do adresu URL (np. https://localhost:8443/yourpath), Na którym certyfikacja nie działa.
  2. Wyeksportuj certyfikat zgodnie z opisem we wspomnianym poście.
  3. Na komputerze z systemem Windows otwórz: Manage computer certificates
  4. Idź do Trusted Root Certification Authorities->Certificates
  5. Zaimportuj tutaj swój your_certification_name.cerplik.

1

Aby Tomcat działający na serwerze Ubuntu, aby dowiedzieć się, która Java jest używana, użyj polecenia „ps -ef | grep tomcat”:

Próba:

/home/mcp01$ **ps -ef |grep tomcat**
tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat

Następnie możemy przejść do: cd /usr/local/java/jdk1.7.0_15/jre/lib/security

Domyślny plik cacerts znajduje się tutaj. Włóż do niego niezaufany certyfikat.


1

dla bezpieczeństwa nie powinniśmy używać samopodpisanych certyfikatów w naszej implementacji. Jeśli jednak chodzi o programowanie, często musimy korzystać ze środowisk testowych, które otrzymały certyfikaty z podpisem własnym. Próbowałem rozwiązać ten problem programowo w kodzie i nie udało mi się. Jednak dodanie certyfikatu do zaufanego sklepu jre naprawiło mój problem. Poniżej znajdują się kroki,

  1. Pobierz certyfikat strony,

  2. Skopiuj certyfikat (np .: plik_certyfikatu.cer) do katalogu $ JAVA_HOME \ Jre \ Lib \ Security

  3. Otwórz CMD w Administratorze i zmień katalog na $ JAVA_HOME \ Jre \ Lib \ Security

  4. Zaimportuj certyfikat do magazynu zaufania, używając polecenia poniżej,

keytool -import -alias ca -plik plik_certyfikatu.cer -keystore cacerts -storepass changeit

Jeśli wystąpił błąd informujący, że keytool nie jest rozpoznawalny, zapoznaj się z tym.

Wpisz tak jak poniżej

Zaufaj temu certyfikatowi: [Tak]

  1. Teraz spróbuj uruchomić kod lub uzyskać dostęp do adresu URL programowo za pomocą Java.

Aktualizacja

Jeśli serwerem aplikacji jest jboss, spróbuj dodać poniżej właściwości systemowej

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

Mam nadzieję że to pomoże!


1

ROZWIĄZANIE DO ROZWIĄZANIA (Alpine Linux)

Aby rozwiązać ten problem w naszych środowiskach aplikacji, przygotowaliśmy następujące polecenia terminala Linux:

cd ~

Wygeneruje plik cert w katalogu domowym.

apk add openssl

To polecenie instaluje openssl w alpejskim systemie Linux. Możesz znaleźć odpowiednie polecenia dla innych dystrybucji Linuksa.

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

Wygenerowano potrzebny plik cert.

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

Zastosował wygenerowany plik do środowiska JRE za pomocą programu „keytool”.

Uwaga: zamień swój DNS na<host-dns-ssl-belongs>

Uwaga 2 : Proszę delikatnie pamiętać, że -nopromptnie wyświetli komunikatu weryfikacyjnego (tak / nie), a -storepass changeitparametr wyłączy monit o podanie hasła i poda wymagane hasło (domyślnie jest to „zmień”). Te dwie właściwości pozwolą ci używać tych skryptów w środowiskach aplikacji, takich jak budowanie obrazu Docker.

Uwaga 3 Jeśli wdrażasz aplikację za pomocą Dockera, możesz wygenerować tajny plik jeden raz i umieścić go w plikach projektu aplikacji. Nie będziesz musiał generować go wielokrotnie.


0

Też mam ten problem.

Próbowałem prawie wszystkiego, dodając certyfikat SSL do .keystore, ale to nie działało z Java1_6_x. Dla mnie pomogło, jeśli zaczniemy używać nowszej wersji Java, Java1_8_x jako JVM.


1
Dla mnie to samo. Aktualizacja oprogramowania Java 1.8.0_91 do 1.8.0_121 rozwiązała problem. Dostałem wyjątek za pomocą Apache HTTPClient.
Devabc

Nadal mam ten problem z uwierzytelnianiem Oauth2
Sofiane

0

Miałem ten problem z Android Studio, gdy jestem za serwerem proxy. Korzystałem z Crashlytics, który próbuje załadować plik mapowania podczas kompilacji.

Dodałem brakujący certyfikat proxy do magazynu zaufania znajdującego się pod adresem /Users/[username]/Documents/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts

za pomocą następującego polecenia: keytool -import -trustcacerts -keystore cacerts -storepass [password] -noprompt -alias [alias] -file [my_certificate_location]

na przykład z domyślnym hasłem do magazynu zaufanych certyfikatów keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias myproxycert -file /Users/myname/Downloads/MyProxy.crt


0

Tylko mały hack. Zaktualizuj adres URL w pliku „hudson.model.UpdateCenter.xml” z https na http

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://updates.jenkins.io/update-center.json</url>
  </site>
</sites>

0

Chcę się włączyć, ponieważ mam środowisko QEMU, w którym muszę pobierać pliki w Javie. Okazuje się, że /etc/ssl/certs/java/cacertsw QEMU ma problem, ponieważ nie pasuje do /etc/ssl/certs/java/cacertsśrodowiska hosta. Środowisko hosta znajduje się za firmowym serwerem proxy, więc Java Cacerts jest dostosowaną wersją.

Jeśli używasz środowiska QEMU, upewnij się, że system hosta może najpierw uzyskać dostęp do plików. Na przykład możesz najpierw wypróbować ten skrypt na komputerze-hoście. Jeśli skrypt działa dobrze na komputerze hosta, ale nie w QEMU, oznacza to, że masz ten sam problem co ja.

Aby rozwiązać ten problem, musiałem wykonać kopię zapasową oryginalnego pliku w QEMU, skopiować plik w środowisku hosta do więzienia chroot QEMU, a następnie java mogłaby normalnie pobierać pliki w QEMU.

Lepszym rozwiązaniem byłoby zamontowanie /etcw środowisku QEMU; nie jestem jednak pewien, czy w tym procesie wpłynie to na inne pliki. Postanowiłem więc użyć tego brzydkiego, ale łatwego obejścia.


0

Wydaje się, że jest to równie dobre miejsce do udokumentowania innego możliwego powodu niesławnego komunikatu o błędzie PKIX. Po zbyt długim spoglądaniu na zawartość magazynu kluczy i zaufanych certyfikatów oraz różne konfiguracje instalacji Java, zdałem sobie sprawę, że mój problem polegał na ... literówce.

Literówka oznaczała, że ​​używałem również magazynu kluczy jako magazynu zaufania. Ponieważ moje firmy główny urząd certyfikacji nie został zdefiniowany jako samodzielny certyfikat w magazynie kluczy, ale tylko jako część łańcucha certyfikatów, i nie został zdefiniowany nigdzie indziej (tj. Cacerts), ciągle pojawiał się błąd PKIX.

Po nieudanym wydaniu (jest to konfiguracja prod, gdzie indziej było ok) i po dwóch dniach drapania się po głowie w końcu zobaczyłem literówkę, a teraz wszystko jest dobrze.

Mam nadzieję, że to komuś pomoże.


-1

dodaj to do swojego kodu:

TrustManager[] trustAllCerts = new TrustManager[]{
           new X509TrustManager() {
               @Override
               public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                   return new X509Certificate[0];
               }

               @Override
               public void checkClientTrusted(
                       java.security.cert.X509Certificate[] certs, String authType) {
               }

               @Override
               public void checkServerTrusted(
                       java.security.cert.X509Certificate[] certs, String authType) {
               }
           }
       };

       try {
           SSLContext sc = SSLContext.getInstance("SSL");
           sc.init(null, trustAllCerts, new java.security.SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
       } catch (GeneralSecurityException e) {
       }

1
Na tej stronie ogólnie nie są mile widziane odpowiedzi kodowe. Czy możesz zredagować swoją odpowiedź, dodając komentarze lub wyjaśnienia do swojego kodu? Wyjaśnienia powinny odpowiadać na pytania takie jak: Co to robi? Jak to robi? Dokąd to zmierza? Jak rozwiązuje problem OP?
mypetlion

1
dodaj to do swojego kodu Nie. Nie dodawaj tego do swojego kodu . Utworzenie SSLContext w ten sposób usuwa wszystkie kontrole bezpieczeństwa, które weryfikują tożsamość serwera, z którym się łączysz. Odpowiedzią na problem utraty kluczy NIE jest usunięcie wszystkich zamków ze wszystkiego, co posiadasz.
Andrew Henle,
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.