Java SSL – Unable to Find Valid Certification Path to Requested Target

httpclientjavasslhandshakeexception

I'm trying to connect to a website using a HttpClient object. It works fine for websites we normally use(Like google). But there is a web site, when I try to connect, my program gives this error..

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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1369)
....................
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:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
...............

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 27 more

When I try to go to this url from the browser, I have to click continue anyway. Otherwise browser will not load the page. It gives a privacy error saying your connection is not private.

How can I overcome this problem in my java application..? I want my software to connect with that url without any error or without asking any confirmation.

Best Answer

TrustSelfSignedStrategy approach

The problem was solved when I used a TrustSelfSignedStrategy object as the Trust material to HttpClient.

        httpClient = HttpClients.custom()
            .setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
                    .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                    .build()
                )
            ).build();

TrustAllStrategy approach

If the above does not work, for example because the certificate served by the server is not a self-signed certificate but just untrusted for other reasons (for example, hostname mismatch), this is an even more brutal approach. Do not use this in production, since it will blindly trust all certificates. This is typically only useful for unit/integration test and other similar scenarios.

        httpClient = HttpClients.custom()
            .setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
                    .loadTrustMaterial(null, new TrustAllStrategy())
                    .build()
                )
            ).build();
Related Question