O erro abaixo ocorre quando tentamos chamar uma url HTTPS cujo Web Server não possui um certificado digital assinado por uma Autoridade Certificadora.
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:1611)
… (omitindo linhas do trace)
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)
… (omitindo linhas do trace)
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)
… (omitindo linhas do trace)
Quando isto ocorre, existem duas abordagens possíveis para que o cliente do Web Server possa realizar a chamada HTTPS sem receber o erro acima apresentado.
São elas:
1 – Dar ao cliente um certificado dizendo que você aceita acessar o Web Server mesmo este não sendo reconhecido por uma Autoridade Certificadora.
Neste caso, os seguintes passos devem ser executados:
- Salvar o certificado digital através de um browser (geralmente existe um cadeado no rodapé do browser que nos dá a opção de salvar o certificado);
- Importar o certificado com o utilitário Keytool (que se encontra na pasta jre/bin);
- Copiar o arquivo “.keystore” gerado;
- Referenciá-lo em seu código.
2 – Fazer o cliente acessar qualquer url HTTPS sem validar o certificado digital do respectivo Web Server.
Neste caso, na aplicação cliente, devemos implementar um método que terá a responsabilidade de dar um bypass nessa validação.
public static void acceptSSL() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
}
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 (Exception e) {
e.printStackTrace();
}
}
Este método deve ser invocado antes da chamada HTTPS, como no exemplo abaixo:
public static void main(String[] args) {
try {
acceptSSL();
String serviceData = callUrl( "https://somehost.com" );
System.out.println(serviceData);
} catch (IOException e) {
e.printStackTrace();
}
}



Caro Paulo Vitor, tudo bem?
Então gostei bastante do seu resumo sobre o livro de Peopleware. Gostaria de saber se você autorizaria eu replicar os textos escritos por você para a turma de graduação onde dou aula. Estamos tratando justamente o tema Peopleware e o seu material está ótimo.
Caso negativo, por favor me informe.
Obrigado, e parabéns pelos textos!
Caro David,
Fico contente que tenha gostado da amostra do livro que publiquei.
Fique a vontade em repassar o conteúdo.
Um abraço.
Paulo,
Estava com esse problemão há bastante tempo e seu artigo veio salvando. Valeu pela ajuda.