Search code examples
javahttpclientsslhandshakeexception

Unable to find valid certification path to requested target - java


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.


Solution

  • 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();