Java 11 introduced the?HTTP Client, an API that made it easier to send HTTP requests with vanilla Java.
By default, it throws an exception if there are certificate path or hostname verification errors in the request.
Let’s see how to bypass certificate validations for cases where this is really necessary.
To ignore both certificate path and hostname verifications, create an?X509ExtendedTrustManager
?extension that doesn't do any verification and use it to init an?SSLContext
?for an?HttpClient
:
var trustManager = new X509ExtendedTrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } @Override public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) { } @Override public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { } }; var sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom()); var client = HttpClient.newBuilder() .sslContext(sslContext) .build();
With this solution, only that client with that custom?SSLContext
?specified will allow insecure requests. So in many cases this is the best option.
You can use the example URLs?https://expired.badssl.com/
?and?https://wrong.host.badssl.com/
?to test:
var expiredRequest = HttpRequest.newBuilder() .uri(URI.create("https://expired.badssl.com/")) .build(); var wrongHostRequest = HttpRequest.newBuilder() .uri(URI.create("https://wrong.host.badssl.com/")) .build(); client.send(expiredRequest, BodyHandlers.discarding()); client.send(wrongHostRequest, BodyHandlers.discarding());
Without disabling verification, this error would occur for an expired?SSL/TLS certificate:
javax.net.ssl.SSLHandshakeException: PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed ... Caused by: java.security.cert.CertificateExpiredException: NotAfter: Sun Apr 12 20:59:59 BRT 2015
And for a wrong hostname:
javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching wrong.host.badssl.com found. ... Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching wrong.host.badssl.com found.
You can set the?jdk.internal.httpclient.disableHostnameVerification
?system property to?"true"
?to disable only hostname verification, as shown in the?Javadoc.
This solution isn’t applied to certificate path verification, so an expired certificate would still cause an exception. And it has the disadvantage of disabling hostname verification for requests from all clients.
If you create an?X509TrustManager
?implementation (instead of an?X509ExtendedTrustManager
?extension) that doesn't do verifications and use it on a client, it will ignore only the certificate path verification:
var sslContext = SSLContext.getInstance("TLS"); var trustManager = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { } }; sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom()); var client = HttpClient.newBuilder() .sslContext(sslContext) .build(); var request = HttpRequest.newBuilder() .uri(URI.create("https://expired.badssl.com/")) .build(); client.send(request, BodyHandlers.discarding());
So this solution isn’t applied to hostname verification.
To disable certificate verification, the best option in most cases is to use an?X509ExtendedTrustManager
?extension that doesn't do any verification, as this will bypass both certificate path and hostname verifications and will only apply to the specified client.