emoleumassi
emoleumassi

Reputation: 5149

SSLHandshakeException: ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:

i try to request a local service with https without certificate check. But i got this execption.

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

here is a part of code:

try {
            RestTemplate restTemplate = new RestTemplate();
            HttpsURLConnection.setDefaultHostnameVerifier(
                    (hostname, session) -> hostname.equals("IPADDRESS"));
            responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        } catch (HttpClientErrorException e) {
            LOGGER.error(e.toString());
        }

what is wrong here?

Upvotes: 1

Views: 5788

Answers (2)

emoleumassi
emoleumassi

Reputation: 5149

Hy,

i resolved it with this code part:

private void disableCertificateVerification() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)                  throws CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws CertificateException {
            }
        } };

        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            HttpsURLConnection.setDefaultHostnameVerifier(
                    (hostname, session) -> hostname.equals("IPADDRESS"));
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            LOGGER.error(e.toString());
        }
    }

and i called this function before i created the RestTemplate.

Upvotes: 1

pedrofb
pedrofb

Reputation: 39261

This problem is due to incomplete trust path for the server certificate: the server certificate is probably not trusted by the client.

Usually the fix is to import the server certificate into the client trust store. The default trustStore is in jre/lib/security/cacerts but is is a better practice to use your own keystore

You can create an SSLSocketFactory and add to your connection before connecting or apply to all connections using the static method

 HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);

This is an example to create the socket factory

/* Load the keyStore that includes the server cert as a "trusted" entry. */
KeyStore keyStore = ... 
TrustManagerFactory tmf = 
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
sslFactory = ctx.getSocketFactory();

Example of loading the keyStore

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trustStore, trustStorePassword);
trustStore.close();

The trust store can also be configured using system properties

 System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile");
 System.setProperty("javax.net.ssl.trustStorePassword", "password");

The simplest way to create the key store file is using the GUI tool Portecle. New KeyStore > Import Trusted certificates

You can import the root certificate of the chain if you want to 'trust' all certificates from root, or import only the server certificate. For a self-signed certificate, import it directly

Upvotes: 1

Related Questions