Echec de la construction du chemin PKIX: impossible de trouver un chemin de certificateion valide vers la cible demandée

J’appelle un service Web HTTPS dont le client suivant:

import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.HttpURLConnection; import java.net.URL; import javax.net.ssl.HttpsURLConnection; /** * Handles http and https connections. It sends XML request over http (or https) * to SOAP web service and receive the XML reply. * * @author mhewedy * @date 30.10.2010 */ public class HttpWSXmlClient { private final Ssortingng ws_url; private byte[] requestData; public HttpWSXmlClient(Ssortingng wsUrl) { this.ws_url = wsUrl; } public void readRequest(Ssortingng xmlRequestFilePath) { try { InputStream istream = new FileInputStream(xmlRequestFilePath); byte[] data = stream2Bytes(istream); istream.close(); this.requestData = data; } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } /** * * @param ps * PrintStream object to send the debugging info to. * @return * @throws IOException */ public byte[] sendAndRecieve(PrintStream ps) throws IOException { if (requestData == null) throw new RuntimeException( "the request data didn't initialized yet."); if (ps != null) ps.println("Request:\n" + new Ssortingng(requestData)); URL url = new URL(ws_url); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // or HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestProperty("content-type", "text/xml"); connection.connect(); OutputStream os = connection.getOutputStream(); os.write(requestData); InputStream is = connection.getInputStream(); byte[] rply = stream2Bytes(is); if (ps != null) ps.println("Response:\n" + new Ssortingng(rply)); os.close(); is.close(); connection.disconnect(); return rply; } public byte[] sendAndRecieve() throws IOException { return sendAndRecieve(null); } private byte[] stream2Bytes(InputStream istream) throws IOException { ByteArrayOutputStream outstream = new ByteArrayOutputStream(); int c; while ((c = istream.read()) != -1) { if (c != 0x0A && c != 0x0D) // prevent new line character from being // written { if (c == 0x09) c = 0x20; // prevent tab character from being written, // instead write single space char outstream.write(c); } } byte[] ret = outstream.toByteArray(); outstream.close(); return ret; } } 

Tester:

 public class Test { private static final Ssortingng WS_URL = "https://some_server/path/to/ws"; public static void main(Ssortingng[] args) throws Exception { HttpWSXmlClient client = new HttpWSXmlClient(WS_URL); client.readRequest("request.xml"); client.sendAndRecieve(System.out); } } 

J’ai eu la sortie suivante:

 Exception in thread "Main Thread" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certificateion path to requested target at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:415) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133) at com.se.swstest.HttpWSXmlClient.sendAndRecieve(HttpWSXmlClient.java:63) at com.se.swstest.Test.main(Test.java:11) Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certificateion path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:285) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191) at sun.security.validator.Validator.validate(Validator.java:218) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014) ... 12 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certificateion path to requested target at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280) ... 18 more 

Ai-je besoin d’un certificate pour être jdk / jre / lib / security ??? J’ai aussi un xxx_IE.crt et xxx_FX.crt (pour Firefox et IE respectivement, et ils ne fonctionnent pas pour le client Java ci-dessus, ai-je besoin d’un certificate spécifique pour le client Java?

Merci.

Vous devez définir le certificate pour bash cette URL. utilisez le code ci-dessous pour définir le fichier de clés:

 System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key"); System.setProperty("javax.net.ssl.trustStorePassword","qwerty"); 

Solution Java 8: Je viens d’avoir ce problème et je l’ai résolu en ajoutant le certificate du site distant à mon fichier de clés Java. Ma solution était basée sur la solution du blog myshittycode , basée sur une solution précédente du blog de mykong . Ces solutions d’article de blog se résument au téléchargement d’un programme appelé InstallCert , une classe Java que vous pouvez exécuter depuis la ligne de commande pour obtenir le certificate. Vous continuez ensuite à installer le certificate dans le fichier de clés de Java.

Le fichier Readme InstallCert a parfaitement fonctionné pour moi. Il vous suffit d’exécuter les commandes suivantes:

  1. javac InstallCert.java
  2. java InstallCert [host]:[port] (Entrez le numéro de liste donné du certificate que vous souhaitez append à la liste lorsque vous exécutez la commande – probablement juste 1 )
  3. keytool -exportcert -alias [host]-1 -keystore jssecacerts -storepass changeit -file [host].cer
  4. sudo keytool -importcert -alias [host] -keystore [path to system keystore] -storepass changeit -file [host].cer

Consultez le fichier README référencé pour un exemple si nécessaire.

Je l’ai rencontré plusieurs fois et c’était dû à une chaîne de certificates incomplète. Si vous utilisez le magasin d’approbation Java standard, il se peut qu’un certificate ne soit pas nécessaire pour terminer la chaîne de certificates requirejse pour valider le certificate du site SSL auquel vous vous connectez.

J’ai rencontré ce problème avec certains certificates DigiCert et j’ai dû append manuellement le certificate intermédiaire.

Voici la solution que j’ai utilisée pour installer le certificate public d’un site dans le fichier de clés du système à utiliser.

Téléchargez le certificate avec la commande suivante:

unix, linux, mac

 openssl s_client -connect [host]:[port|443] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt 

les fenêtres

 openssl s_client -connect [host]:[port|443] < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt 

Cela créera un fichier crt pouvant être utilisé pour importer dans un magasin de clés.

Installez le nouveau certificate avec la commande:

 keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt 

Cela vous permettra d’importer le nouveau certificate depuis le site à l’origine de l’exception.

J’avais frappé cela lorsque j’essayais de lancer une requête SOAP à partir du code Java. Ce qui a fonctionné pour moi était:

  1. Obtenez le certificate du serveur en tapant l’URL dans le navigateur: http://docs.bvstools.com/home/ssl-documentation/exporting-certificatee-authorities-cas-from-a-website Ce lien a toutes les étapes pour obtenir le serveur certificate

  2. Une fois que vous avez le certificate de serveur avec vous, suivez http://java.globinch.com/enterprise-java/security/pkix-path-building-failed-validation-sun-security-validatorexception/#Valid-Certification-Path-to- Cible demandée .

Copier le texte du lien, au cas où ce lien serait mort:

Tout ce que vous devez faire pour corriger cette erreur est d’append le certificate de serveur à votre magasin de clés Java approuvé. Vous devez d’abord télécharger le document à partir du serveur.

Une fois que vous avez le certificate sur votre disque dur, vous pouvez l’importer dans Java Trust Store. Pour importer le certificate dans le magasin de clés Java approuvé, vous pouvez utiliser l’outil java “keytool”. À l’invite de commande, accédez au dossier JRE bin, dans mon cas, le chemin est le suivant: C: \ Program Files \ Java \ jdk1.7.0_75 \ jre \ bin. Ensuite, utilisez la commande keytool comme suit pour importer le certificate dans JRE.

keytool -import -alias _alias_name_ -keystore .. \ lib \ security \ cacerts -file _path_to_cer_file

Il vous demandera un mot de passe. Par défaut, le mot de passe est «changeit». Si le mot de passe est différent, vous ne pourrez peut-être pas importer le certificate.

Sous Mac OS, je devais ouvrir le certificate auto-signé du serveur avec l’outil d’access au trousseau du système, l’importer, le dobublecliquer, puis sélectionner “Toujours faire confiance” (même si je le définissais dans l’importateur). Avant cela, bien sûr, java key a pris avec -importcert pour importer le même fichier dans le stockage cacert.

Pour moi, j’ai rencontré cette erreur lors de l’appel d’un webservice, assurez-vous que le site a un SSL valide, c’est-à-dire que le logo sur le côté de l’URL est coché.

J’ai également fait face à ce type de problème.J’utilise le serveur tomcat puis j’ai mis le dossier approuvé dans tomcat puis son début de travail.Et aussi j’ai remplacé JDK1.6 avec 1.7 puis aussi son fonctionnement.Enfin j’apprends SSL puis j’ai résolu ce type de problèmes .Tout d’abord, vous devez télécharger les certificates à partir de ce serveur de fournisseur de services. Vous êtes alors une poignée de main réussie. 1.Essayez de placer le dossier approuvé sur votre serveur Prochaine manière 2.use jdk1.7

Next 3.Essayez de télécharger des certificates valides à l’aide de SSL

Si vous n’avez pas besoin de la sécurité SSL, vous voudrez peut-être l’éteindre.

  /** * disable SSL */ private void disableSslVerification() { try { // Create a trust manager that does not validate certificatee chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, Ssortingng authType) { } public void checkServerTrusted(X509Certificate[] certs, Ssortingng authType) { } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(Ssortingng hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } }