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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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:
1 2 3 4 5 6 7 8 9 |
public static void main(String[] args) { try { acceptSSL(); String serviceData = callUrl( "https://somehost.com" ); System.out.println(serviceData); } catch (IOException e) { e.printStackTrace(); } } |
[:pb]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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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:
1 2 3 4 5 6 7 8 9 |
public static void main(String[] args) { try { acceptSSL(); String serviceData = callUrl( "https://somehost.com" ); System.out.println(serviceData); } catch (IOException e) { e.printStackTrace(); } } |