adam bien's blog

How To Connect to an Insecure SSL Endpoint with Java HTTP Client 📎

To connect to an insecure https endpoint (e.g. with self-signed certificates, here https://localhost:8443) with Java 11+ HTTP Client, you disable certificate checks in SSLContext first:

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

static SSLContext insecureContext() {
    TrustManager[] noopTrustManager = new TrustManager[]{
        new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] xcs, String string) {}
            public void checkServerTrusted(X509Certificate[] xcs, String string) {}
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
    };
    try {
        SSLContext sc = SSLContext.getInstance("ssl");
        sc.init(null, noopTrustManager, null);
        return sc;
    } catch (KeyManagementException | NoSuchAlgorithmException ex) {}
}    

The hostname verification is deactivated via Java's System properties. After setting the properties and passing the insecure SSLContext, the endpoint is ready to connect to a HTTP endpoint with an invalid SSL certificate:


@Test
public void connectToInsecureEndpoint() throws IOException, InterruptedException {
    var properties = System.getProperties(); 
    properties.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());

    var uri = URI.create("https://localhost:8443");
    var client = HttpClient.newBuilder()
            .sslContext(insecureContext())
            .build();

    var request = HttpRequest.newBuilder(uri)
            .GET()
            .build();
    
    var content = client.send(request, BodyHandlers.ofString()).body();
    assertNotNull(content);
}    

Without the disabling the hostname verification you will get the following exception:


javax.net.ssl.SSLHandshakeException: No name matching localhost found
    at airhacks.HttpClientTest.connectToInsecureEndpoint(HttpClientTest.java:41)
Caused by: javax.net.ssl.SSLHandshakeException: No name matching localhost found
Caused by: java.security.cert.CertificateException: No name matching localhost found

...and without setting the insecure SSLContext the following exception is thrown:


javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at airhacks.HttpClientTest.connectToInsecureEndpoint(HttpClientTest.java:41)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target