Search code examples
javasslhttpshttpclientapache-httpclient-4.x

Apache Http Client SSL certificate error


I know it's been asked before but I tried all the solutions that I found and it's still not working.

Basically, I'm trying to get some content via Apache Http Client (4.3) and the website that I'm connecting is having some SSL issues.

First, I was getting and SSLException with and unrecognized_name message. I tried to get around this by setting the jsse.enableSNIExtension property to false.

Then, I got this exception: 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

I then tried supplying my won SSLFactory that would accept all certificates but I'm still getting the same exception. Here's my code:

private static void sslTest() throws Exception {
    System.setProperty("jsse.enableSNIExtension", "false");

    SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            .useTLS()
            .build();

    SSLConnectionSocketFactory connectionFactory =
            new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier());

    CookieStore cookieStore = new BasicCookieStore();
    HttpClientContext context = HttpClientContext.create();
    context.setCookieStore(cookieStore);

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(connectionFactory)
            .setDefaultCookieStore(cookieStore)
            .build();

    URI uri = new URIBuilder()
            .setScheme("https")
            .setHost(BASE_URL)
            .build();

    String responseBody = httpclient.execute(new HttpGet(uri), RESPONSE_HANDLER);
}

All help is greatly appreciated!


Solution

  • Please also note that trusting self-signed certs does not mean trusting any arbitrary cert.

    Try setting up your SSL context this way:

    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, 
        new TrustStrategy() {
            @Override
            public boolean isTrusted(final X509Certificate[] chain, final String authType) 
            throws CertificateException {
                return true;
            }
        })
        .useTLS()
        .build();
    

    Please also note that generally trusting certificates indiscriminately defeats the purpose of using SSL in the first place. Use when absolutely necessary or for testing only