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.
Disabling all certificate verifications for a specific client
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());
Errors you would get
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.
Disabling hostname verification by system property
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.
Disabling only certificate path verification
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.文章来源:https://www.toymoban.com/news/detail-803107.html
Conclusion
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.文章来源地址https://www.toymoban.com/news/detail-803107.html
到了这里,关于How to disable certificate validations in the Java HTTP Client的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!