Falha no desenvolvimento do caminho do PKIX: impossível encontrar o caminho de certificação válido para o destino solicitado

Eu estou chamando algum serviço web HTTPS que o seguinte cliente:

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 String ws_url; private byte[] requestData; public HttpWSXmlClient(String wsUrl) { this.ws_url = wsUrl; } public void readRequest(String 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 String(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 String(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; } } 

Teste:

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

Eu tenho a seguinte saída:

 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 certification 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 certification 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 certification 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 

Preciso de algum certificado para ser colocado em jdk / jre / lib / security ??? Além disso, eu tenho um xxx_IE.crt e xxx_FX.crt (para o Firefox e IE, respectivamente, e eles não funcionam para o cliente Java acima, então eu preciso de um certificado específico para o cliente Java?

Obrigado.

Você precisa definir o certificado para atingir este URL. use abaixo o código para definir keystore:

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

Solução Java 8: Acabei de ter este problema e o resolvi adicionando o certificado do site remoto ao meu keystore Java. Minha solução foi baseada na solução do blog myshittycode , baseado em uma solução anterior no blog do mykong . Essas soluções de artigo de blog resumem-se ao download de um programa chamado InstallCert , que é uma class Java que você pode executar a partir da linha de comando para obter o certificado. Em seguida, você prossegue para instalar o certificado no keystore do Java.

O Readme InstallCert funcionou perfeitamente para mim. Você só precisa executar os seguintes comandos:

  1. javac InstallCert.java
  2. java InstallCert [host]:[port] (Digite o número da lista fornecida do certificado que você deseja adicionar na lista ao executar o comando – provavelmente apenas 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

Veja o arquivo README referenciado para um exemplo, se necessário.

Eu me deparei com isso algumas vezes e foi devido a uma cadeia de certificados estar incompleta. Se você estiver usando o armazenamento confiável java padrão, ele pode não ter um certificado necessário para concluir a cadeia de certificados que é necessária para validar o certificado do site SSL ao qual você está se conectando.

Eu corri para este problema com alguns certificados DigiCert e tive que adicionar manualmente o certificado intermediário eu mesmo.

Aqui está a solução que usei para instalar o certificado público de um site no keystore do sistema para uso.

Baixe o certificado com o seguinte comando:

unix, linux, mac

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

janelas

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

Isso criará um crt que pode ser usado para importar em um keystore.

Instale o novo certificado com o comando:

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

Isso permitirá que você importe o novo certificado do site que está causando a exceção.

Eu tinha atingido isso quando eu estava tentando iniciar uma solicitação SOAP do código Java. O que funcionou para mim foi:

  1. Obter o certificado do servidor, batendo a URL no navegador: http://docs.bvstools.com/home/ssl-documentation/exporting-certificate-authorities-cas-from-a-website Este link tem todas as etapas para obter o servidor certificado

  2. Depois de ter o certificado de servidor com você, siga http://java.globinch.com/enterprise-java/security/pkix-path-building-failed-validation-sun-security-validatorexception/#Valid-Certification-Path-to- Meta Solicitada .

Copiando o texto do link, caso esse link morra:

Tudo o que você precisa fazer para corrigir esse erro é adicionar o certificado do servidor ao seu armazenamento de chaves Java confiável. Primeiro você precisa baixar o documento do servidor.

Depois de ter o certificado em seu disco rígido, você pode importá-lo para o truststore Java. Para importar o certificado para o armazenamento de chaves Java confiável, você pode usar a ferramenta java ‘keytool’. No prompt de comando, navegue até a pasta bin do JRE, no meu caso, o caminho é: C: \ Arquivos de programas \ Java \ jdk1.7.0_75 \ jre \ bin. Em seguida, use o comando keytool da seguinte maneira para importar o certificado para o JRE.

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

Ele pedirá uma senha. Por padrão, a senha é “changeit”. Se a senha for diferente, talvez você não consiga importar o certificado.

No Mac OS, tive que abrir o certificado autoassinado do servidor com a ferramenta de Acesso às Chaves do sistema, importá-lo, baixá-lo e selecionar “Sempre confiar” (mesmo que eu configure o mesmo no importador). Antes disso, é claro que eu corri a tecla java levou com -importcert para importar o mesmo arquivo para cacert armazenamento.

Para mim, eu encontrei esse erro ao invocar uma chamada de serviço da Web, verifique se o site tem um SSL válido, ou seja, se o logotipo na lateral da URL está marcado, caso contrário, adicione o certificado ao armazenamento de chaves confiável em sua máquina

Eu também enfrentei esse tipo de problema.Estou usando o servidor tomcat, em seguida, coloquei a pasta endossada no tomcat e começou a trabalhar.E também substituí o JDK1.6 por 1.7 e também o seu funcionamento.Finalmente, eu aprendo SSL e resolvi esse tipo de problema Primeiro, você precisa baixar os certificados do servidor do provedor de serviço. Depois, você é bem-sucedido. 1. Tente colocar pasta endossada no seu servidor Próxima maneira 2. use jdk1.7

Próximo 3.Tente baixar certificados válidos usando SSL