web-dev-qa-db-fra.com

Résolution de javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: la création du chemin PKIX a échoué Erreur?

Edit: - J'ai essayé de formater la question et accepté la réponse de manière plus présentable chez moi Blog

Voici le problème original.

Je reçois cette erreur:

message détaillé Sun.security.validator.ValidatorException: la construction du chemin PKIX a échoué:
Sun.security.provider.certpath.SunCertPathBuilderException: impossible de trouver le chemin de certification valide vers la cible demandée

cause javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: la construction du chemin PKIX a échoué: Sun.security.provider.certpath.SunCertPathBuilderException: impossible de trouver un chemin de certification valide pour la cible demandée

J'utilise Tomcat 6 en tant que serveur Web. J'ai deux applications Web HTTPS installées sur différents Tomcats sur des ports différents mais sur le même ordinateur. Dites App1(port 8443) et App2(port 443). App1 se connecte à App2. Lorsque App1 se connecte à App2 j'obtiens l'erreur ci-dessus. Je sais que c’est une erreur très courante, j’ai rencontré de nombreuses solutions sur différents forums et sites. J'ai l'entrée ci-dessous dans server.xml des deux Tomcats:

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

Chaque site indique la même raison pour laquelle le certificat donné par app2 ne se trouve pas dans le magasin sécurisé de app1 jvm. Cela semble être vrai aussi quand j'ai essayé de frapper la même URL dans le navigateur IE, cela fonctionne (avec réchauffement, il y a un problème avec le certificat de sécurité de ce site Web. Je dis ici de continuer vers ce site). Mais lorsque le même URL est touché par le client Java (dans mon cas), l'erreur ci-dessus apparaît. Donc, pour le mettre dans le truststore, j'ai essayé ces trois options:

Option1

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

Option2 Paramètre ci-dessous dans la variable d'environnement

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

Option3 Paramètre ci-dessous dans la variable d'environnement

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

Mais rien n'a fonctionné .

Ce qui a finalement fonctionné exécute l'approche Java suggérée dans Comment gérer des certificats SSL non valides avec Apache HttpClient? par Pascal Thivent c'est-à-dire en exécutant le programme InstallCert.

Mais cette approche convient pour l'installation de devbox mais je ne peux pas l'utiliser en environnement de production.

Je me demande pourquoi trois approches mentionnées ci-dessus n'ont pas fonctionné alors que j'ai mentionné les mêmes valeurs dans server.xml du app2 serveur et les mêmes valeurs dans le magasin de clés de confiance en définissant

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

dans le programme app1.

Pour plus d'informations, voici comment je crée la connexion:

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());
367
M Sach

Vous devez ajouter le certificat pour App2 au fichier de clés certifiées de la JVM utilisée située à l'adresse %Java_HOME%\lib\security\cacerts.

Tout d'abord, vous pouvez vérifier si votre certificat est déjà dans le fichier de clés certifiées en exécutant la commande suivante: keytool -list -keystore "%Java_HOME%/jre/lib/security/cacerts" (vous n'avez pas besoin de fournir de mot de passe)

Si votre certificat est manquant, vous pouvez l'obtenir en le téléchargeant avec votre navigateur et en l'ajoutant au fichier de clés certifiées à l'aide de la commande suivante:

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

Après l'importation, vous pouvez exécuter la première commande à nouveau pour vérifier si votre certificat a été ajouté.

Les informations sur Sun/Oracle peuvent être trouvées ici .

357
SimonSez

javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: la construction du chemin PKIX a échoué: Sun.security.provider.certpath.SunCertPathBuilderException: impossible de trouver un chemin de certification valide pour la cible demandée

• Lorsque j'ai eu l'erreur, j'ai essayé de trouver la signification de l'expression dans Google. Ce problème se produit lorsqu'un serveur modifie son certificat SSL HTTPS et que notre ancienne version de Java ne reconnaît pas le autorité de certification racine (CA).

• Si vous pouvez accéder à l'URL HTTPS dans votre navigateur, il est possible de mettre à jour Java pour reconnaître l'autorité de certification racine.

• Dans votre navigateur, accédez à l'URL HTTPS à laquelle Java ne peut pas accéder. Cliquez sur la chaîne de certificat HTTPS (il y a une icône de verrou dans Internet Explorer), cliquez sur le verrou pour afficher le certificat.

• Allez dans "Détails" du certificat et "Copier dans un fichier". Copiez-le au format Base64 (.cer). Il sera sauvegardé sur votre bureau.

• Installez le certificat en ignorant toutes les alertes.

• C’est ainsi que j’ai recueilli les informations de certificat de l’URL à laquelle j’essayais d’accéder.

Maintenant, je devais créer ma version Java pour connaître le certificat afin qu’elle ne refuse pas non plus de reconnaître l’URL. À cet égard, je dois mentionner que j'ai recherché sur Google que les informations du certificat racine sont conservées par défaut dans l'emplacement \ jre\lib\security du JDK, et que le mot de passe par défaut pour accéder est: changeit. =

Pour afficher les informations sur les transactions, les procédures à suivre sont les suivantes:

• Cliquez sur le bouton Démarrer -> Exécuter

• Tapez cmd. La commande Invite s'ouvre (vous devrez peut-être l'ouvrir en tant qu'administrateur).

• Allez dans votre répertoire Java/jreX/bin

• Tapez ce qui suit

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

Il donne la liste des certificats actuels contenus dans le magasin de clés. Cela ressemble à quelque chose comme ça:

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

Entrez le mot de passe du magasin de clés: changeit

Type de magasin de clés: jks

Fournisseur de fichier de clés: Sun

Votre magasin de clés contient 44 entrées

verisignclass3g2ca, 26 mars 2004, confidenceCertEntry,

Empreinte digitale du certificat (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9

entrustclientca, 9 janvier 2003, trustedCertEntry,

Empreinte digitale du certificat (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4

thawtepersonalbasicca, 13 février 1999, digne de confiance, entrée,

Empreinte digitale du certificat (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41

addtrustclass1ca, 1 er mai 2006, trustedCertEntry,

Empreinte digitale du certificat (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC

verisignclass2g3ca, 26 mars 2004, confidenceCertEntry,

Empreinte digitale du certificat (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6

• Maintenant, je devais inclure le certificat précédemment installé dans les cacerts.

• Pour cela, voici la procédure:

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

Si vous utilisez Java 7:

keytool –importcert –trustcacerts –alias ALIASNAME -fichier PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass change change

• Il ajoutera ensuite les informations de certificat dans le fichier cacert.

C'est la solution que j'ai trouvée pour l'exception mentionnée ci-dessus !!

162
NDeveloper

Comment travailler avec Tomcat 7

Je souhaitais prendre en charge un certificat auto-signé dans une application Tomcat, mais l'extrait de code suivant ne fonctionnait pas

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);
    }
}

voici ce qui a résolu mon problème:

1) Téléchargez le fichier .crt)

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • remplacez <your domain> par votre domaine (par exemple jossef.com)

2) Appliquer le fichier .crt dans le magasin de certificats cacerts de Java.

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <Java HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
  • remplacez <your domain> par votre domaine (par exemple jossef.com)
  • remplacez <Java HOME> par votre répertoire personnel Java

3) le pirater

Même si iv'e a installé mon certificat dans les magasins de certificats par défaut de Java, Tomcat l'ignore (semble ne pas avoir été configuré pour utiliser les magasins de certificats par défaut de Java).

Pour pirater ceci, ajoutez ce qui suit quelque part dans votre code:

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

// ...
33
Jossef Harush

Dans mon cas, le problème était que le serveur Web envoyait uniquement le certificat et l'autorité de certification intermédiaire, pas l'autorité de certification racine. L'ajout de cette option de machine virtuelle Java a résolu le problème: -Dcom.Sun.security.enableAIAcaIssuers=true

La prise en charge de la méthode d'accès client de l'extension Authority Information Access est disponible. Il est désactivé par défaut pour des raisons de compatibilité et peut être activé en définissant la propriété système com.Sun.security.enableAIAcaIssuers sur la valeur true.

Si défini sur true, l'implémentation PKIX de CertPathBuilder dans Sun utilise les informations de l'extension AIA d'un certificat (en plus des CertStores spécifiées) pour rechercher le certificat de l'autorité de certification émettrice, à condition qu'il s'agisse d'un URI de type ldap, http ou ftp.

Source

8
Guillaume

Mon fichier cacerts était totalement vide. J'ai résolu ce problème en copiant le fichier cacerts à partir de ma machine Windows (utilisant Oracle Java 7) et le scp en Linux (OpenJDK).

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

puis sur la machine linux

cp /tmp/cacerts /etc/ssl/certs/Java/cacerts

Cela a très bien fonctionné jusqu'à présent.

5
Ryan Shillington

Une autre raison pourrait être une version obsolète de JDK. J'utilisais jdk version 1.8.0_60, la mise à jour vers la dernière version résolue le problème du certificat.

5
Ali Ismayilov

Le code ci-dessous fonctionne pour moi:

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
Sandip S.

En utilisant Tomcat 7 sous Linux, cela a fait l'affaire.

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

Sous Linux, $Java_HOME n'est pas toujours configuré, mais généralement /etc/alternatives/jre pointe sur $Java_HOME/jre.

4
Cedric Simon

Pour moi, cette erreur est également apparue lors de la tentative de connexion à un processus derrière un proxy inverse NGINX gérant le protocole SSL.

Il s'est avéré que le problème était un certificat sans la chaîne entière de certificats concaténés. Lorsque j'ai ajouté des certificats intermédiaires, le problème a été résolu.

J'espère que cela t'aides.

4
YaDa

J'utilisais jdk1.8.0_171 lorsque je rencontrais le même problème. J'ai essayé les 2 meilleures solutions ici (ajouter un certificat en utilisant keytool et une autre solution qui contient un hack), mais elles ne fonctionnaient pas pour moi.

J'ai mis à niveau mon JDK vers 1.8.0_181 et cela a fonctionné à merveille.

4
avp

j'ai écrit un petit script Win32 (WinXP 32bit testet) stupide cmd (ligne de commande) qui recherche toutes les versions de Java dans les fichiers de programme et y ajoute un certificat. Le mot de passe doit être le "changeit" par défaut ou le changer vous-même dans le script :-)

@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
mons droid

Pour Tomcat s'exécutant sur un serveur Ubuntu, utilisez la commande "ps -ef | grep Tomcat" pour savoir quel Java est utilisé:

Échantillon:

/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

Ensuite, nous pouvons entrer dans: cd /usr/local/Java/jdk1.7.0_15/jre/lib/security

Par défaut cacerts le fichier se trouve ici. Insérez-y le certificat non approuvé.

1
oraclesoon

J'ai aussi ce problème.

J'ai presque tout essayé en ajoutant le certificat SSL à .keystore, mais cela ne fonctionnait pas avec Java1_6_x. Pour moi, cela a aidé si nous commençons à utiliser une version plus récente de Java, Java1_8_x en tant que JVM.

0
Nubian

Pour MacOS X ci-dessous, la commande exacte a fonctionné pour moi; je devais essayer avec double hypen dans l'option 'importcert' qui fonctionnait:

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
0
apandey846

pour des raisons de sécurité, nous ne devrions pas utiliser de certificats auto-signés dans notre mise en œuvre. Cependant, en matière de développement, nous devons souvent utiliser des environnements d’essai dotés de certificats auto-signés. J'ai essayé de résoudre ce problème par programmation dans mon code et j'échoue. Cependant, en ajoutant le certificat à jre trust-store a résolu mon problème. S'il vous plaît trouver ci-dessous les étapes,

  1. Télécharger le site cert,

  2. Copiez le certificat (ex: cert_file.cer) dans le répertoire $ Java_HOME\Jre\Lib\Security

  3. Ouvrez CMD dans Administrator et modifiez le répertoire en $ Java_HOME\Jre\Lib\Security.

  4. Importez le certificat dans un magasin de données de confiance à l'aide de la commande ci-dessous,

keytool -import -alias ca -file cert_file.cer -keystore cacerts -storepass changeit

Si vous avez une erreur disant que keytool n'est pas reconnaissable, veuillez reportez-vous à ceci.

Tapez oui comme ci-dessous

Faites confiance à ce certificat: [Oui]

  1. Maintenant, essayez d'exécuter votre code ou d'accéder à l'URL par programme en utilisant Java.

Mettre à jour

Si votre serveur d'applications est jboss, essayez d'ajouter la propriété système ci-dessous.

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

J'espère que cela t'aides!

0
tk_

Je rencontre ce problème avec AndroidStudio, Charles Proxy, JUnit et Robolectric. Merci @SimonSez je pourrais résoudre le problème.

Remarque: Le point clé modifiant cacerts pouvant être à l'origine de problèmes (par exemple mise à jour de l'IDE ) I Je vous recommanderais de copier le fichier original cacerts dans un répertoire distinct et de les manipuler si nécessaire.

  1. %Java_HOME% - Android utilise un autre JavaHome. Vous pouvez trouver un chemin complet dans l'onglet UnitTests resulr. Dans mon cas c'est /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home

    enter image description here

  2. Télécharger le certificat Charles (par exemple, le dossier Downloads)

  3. Lancer la commande

    Sudo keytool -import -noprompt -trustcacerts -alias charles -file <path to Charles certificate.pem> -keystore "Java_HOME/jre/lib/security/cacerts" -storepass changeit

    Par exemple

    Sudo keytool -import -noprompt -trustcacerts -alias charles -file ~/Downloads/charles-ssl-proxying-certificate.pem -keystore "/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts" -storepass changeit

Le documentaire officiel de Charles

0
yoAlex5