- Ignoring SSL certificate in Apache HttpClient 4.3
- java — ignore expired ssl certificate
- Is it possible to get Java to ignore the «trust store» and just accept whatever SSL certificate it gets?
- 5 Answers 5
- Make a connection to a HTTPS server from Java and ignore the validity of the security certificate
- 2 Answers 2
Ignoring SSL certificate in Apache HttpClient 4.3
The code below works for trusting self-signed certificates. You have to use the TrustSelfSignedStrategy when creating your client:
SSLContextBuilder builder = new SSLContextBuilder(); builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( builder.build()); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory( sslsf).build(); HttpGet httpGet = new HttpGet("https://some-server"); CloseableHttpResponse response = httpclient.execute(httpGet); try < System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); >finally
I did not include the SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER on purpose: The point was to allow testing with self signed certificates so you don’t have to acquire a proper certificate from a certification authority. You can easily create a self-signed certificate with the correct host name, so do that instead of adding the SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER flag.
I had to add the argument SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER to the constructor to get this working with the HttpClientBuilder (as mentioned in holmis83’s response to vasekt).
I also had to use the ALLOW_ALL_HOSTNAME_VERIFIER: SSLConnectionSocketFactory(builder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
The answer is pretty old, but I’m pretty sure I meant this one: hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…. As you can see it’s deprecated. Maybe later I will update the answer for the latest version
If you are using PoolingHttpClientConnectionManager procedure above doesn’t work, custom SSLContext is ignored. You have to pass socketFactoryRegistry in contructor when creating PoolingHttpClientConnectionManager.
SSLContextBuilder builder = SSLContexts.custom(); builder.loadTrustMaterial(null, new TrustStrategy() < @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException < return true; >>); SSLContext sslContext = builder.build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext, new X509HostnameVerifier() < @Override public void verify(String host, SSLSocket ssl) throws IOException < >@Override public void verify(String host, X509Certificate cert) throws SSLException < >@Override public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException < >@Override public boolean verify(String s, SSLSession sslSession) < return true; >>); Registry socketFactoryRegistry = RegistryBuilder . create().register("https", sslsf) .build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager( socketFactoryRegistry); CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(cm).build();
Instead of building your own X509HostnameVerifier, you can use SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER.
As marked below by @rich95, the default for HttpClients is to give you a PoolingHttpClient, so this is relevant very often. I had to try quite a few of these answers before finding I needed this.
Tried to apply this on WebSphere and got «java.security.KeyStoreException: IBMTrustManager: Problem accessing trust store java.io.IOException: Invalid keystore format » To avoid you need pass KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); instead of null to builder.loadTrustMaterial
Actually, with HttpClient 4.5, both HttpClients.custom().setConnectionManager(cm).build() and HttpClients.custom().setSSLSocketFactory(connectionFactory).build() will work, so you don’t need to create a PoolingHttpClientConnectionManager
How to use PoolingHttpClientConnectionManager after creating this , my code is working but i want to know does connection pooling works or not
As an addition to the answer of @mavroprovato, if you want to trust all certificates instead of just self-signed, you’d do (in the style of your code)
builder.loadTrustMaterial(null, new TrustStrategy() < public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException < return true; >>);
or (direct copy-paste from my own code):
import javax.net.ssl.SSLContext; import org.apache.http.ssl.TrustStrategy; import org.apache.http.ssl.SSLContexts; // . SSLContext sslContext = SSLContexts .custom() //FIXME to contain real trust store .loadTrustMaterial(new TrustStrategy() < @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException < return true; >>) .build();
And if you want to skip hostname verification as well, you need to set
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory( sslsf).setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE).build();
as well. (ALLOW_ALL_HOSTNAME_VERIFIER is deprecated).
Obligatory warning: you shouldn’t really do this, accepting all certificates is a bad thing. However there are some rare use cases where you want to do this.
As a note to code previously given, you’ll want to close response even if httpclient.execute() throws an exception
CloseableHttpResponse response = null; try < response = httpclient.execute(httpGet); System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); >finally < if (response != null) < response.close(); >>
Code above was tested using
org.apache.httpcomponents httpclient 4.5.3
And for the interested, here’s my full test set:
import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.TrustStrategy; import org.apache.http.util.EntityUtils; import org.junit.Test; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLPeerUnverifiedException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public class TrustAllCertificatesTest < final String expiredCertSite = "https://expired.badssl.com/"; final String selfSignedCertSite = "https://self-signed.badssl.com/"; final String wrongHostCertSite = "https://wrong.host.badssl.com/"; static final TrustStrategy trustSelfSignedStrategy = new TrustSelfSignedStrategy(); static final TrustStrategy trustAllStrategy = new TrustStrategy()< public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException < return true; >>; @Test public void testSelfSignedOnSelfSignedUsingCode() throws Exception < doGet(selfSignedCertSite, trustSelfSignedStrategy); >@Test(expected = SSLHandshakeException.class) public void testExpiredOnSelfSignedUsingCode() throws Exception < doGet(expiredCertSite, trustSelfSignedStrategy); >@Test(expected = SSLPeerUnverifiedException.class) public void testWrongHostOnSelfSignedUsingCode() throws Exception < doGet(wrongHostCertSite, trustSelfSignedStrategy); >@Test public void testSelfSignedOnTrustAllUsingCode() throws Exception < doGet(selfSignedCertSite, trustAllStrategy); >@Test public void testExpiredOnTrustAllUsingCode() throws Exception < doGet(expiredCertSite, trustAllStrategy); >@Test(expected = SSLPeerUnverifiedException.class) public void testWrongHostOnTrustAllUsingCode() throws Exception < doGet(wrongHostCertSite, trustAllStrategy); >@Test public void testSelfSignedOnAllowAllUsingCode() throws Exception < doGet(selfSignedCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE); >@Test public void testExpiredOnAllowAllUsingCode() throws Exception < doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE); >@Test public void testWrongHostOnAllowAllUsingCode() throws Exception < doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE); >public void doGet(String url, TrustStrategy trustStrategy, HostnameVerifier hostnameVerifier) throws Exception < SSLContextBuilder builder = new SSLContextBuilder(); builder.loadTrustMaterial(trustStrategy); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( builder.build()); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory( sslsf).setSSLHostnameVerifier(hostnameVerifier).build(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpclient.execute(httpGet); try < System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); >finally < response.close(); >> public void doGet(String url, TrustStrategy trustStrategy) throws Exception < SSLContextBuilder builder = new SSLContextBuilder(); builder.loadTrustMaterial(trustStrategy); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( builder.build()); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory( sslsf).build(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpclient.execute(httpGet); try < System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); >finally < response.close(); >> >
java — ignore expired ssl certificate
You should build a TrustManager that wraps the default trust manager, catches the CertificiateExpiredException and ignores it.
Note: as detailed in this answer, whether or not this is secure is very much implementation dependent. In particular, it relies on the date validation being done last, after everything else has been checked properly.
Something along these lines should work:
TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); // Initialise the TMF as you normally would, for example: tmf.init((KeyStore)null); TrustManager[] trustManagers = tmf.getTrustManagers(); final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0]; TrustManager[] wrappedTrustManagers = new TrustManager[] < new X509TrustManager() < public java.security.cert.X509Certificate[] getAcceptedIssuers() < return origTrustmanager.getAcceptedIssuers(); >public void checkClientTrusted(X509Certificate[] certs, String authType) < origTrustmanager.checkClientTrusted(certs, authType); >public void checkServerTrusted(X509Certificate[] certs, String authType) < try < origTrustmanager.checkServerTrusted(certs, authType); >catch (CertificateExpiredException e) <> > > >; SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, wrappedTrustManagers, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
The trust managers throw CertificateException s (see subclasses for details) when something is wrong with a certificate. Be specific in what you want to catch/ignore. Everything you really want validated has to be checked before what you catch is potentially thrown, or you’ll have to validate it manually too. Anything more relaxed than this (in particular, not doing anything and therefore not throwing any exception) will ignore the certificate verification and validation altogether, which is about the same as using anonymous cipher suites or ignoring authentication. This would defeat the security purpose of using SSL/TLS (as opposed to being only a bit more flexible on the expiry date).
Is it possible to get Java to ignore the «trust store» and just accept whatever SSL certificate it gets?
Ignoring the certificate verification step is a bad idea. There’s hardly any point talking secretly to someone if you haven’t made sure who it is in the first place. Option 2 (a local trust store) is easy enough to use.
Ignoring verification step is fine in some circumstances—for example, if you are on an isolated network and SSL is the only enabled service not because of policy, but because your admin doesn’t know how to enable the non-SSL service.
I don’t think it is good idea to by-pass cert truststore validation. Especially if the remote server is outside your control. For your case maybe self-sign cert issue. If you validated the issuer, then you can just adds to truststore using keytool. This is better than using custom TrustManager that blindly accept certificates.
5 Answers 5
Working code ( in jdk1.6.0_23) for #1.
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate;
The actual trust all TrustManager code.
TrustManager trm = new X509TrustManager() < public X509Certificate[] getAcceptedIssuers() < return null; >public void checkClientTrusted(X509Certificate[] certs, String authType) < >public void checkServerTrusted(X509Certificate[] certs, String authType) < >>; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, new TrustManager[] < trm >, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
Make a connection to a HTTPS server from Java and ignore the validity of the security certificate
I’ve been testing a system that accesses a group of https servers with different keys, some of which are invalid and all of them are not in the local key store for my JVM. I am really only testing things out, so I don’t care about the security at this stage. Is there a good way to make POST calls to the server and tell Java not to worry about the security certificates? My google searches for this have brought up some code examples that make a class to do the validation, that always works, but I cannot get it to connect to any of the servers.
Thanks BalusC that works perfectly. I tried 3 or 4 that compiled and ran fine but did not work. Could you make this an answer?
Done. But in the future please mention right in the question which examples exactly you tried along with links 🙂
2 Answers 2
With Googled examples, you mean among others this one?
Update: the link broke, so here’s an extract of relevance which I saved from the internet archive:
// Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] < new X509TrustManager() < public java.security.cert.X509Certificate[] getAcceptedIssuers() < return null; >public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) < >public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) < >> >; // Install the all-trusting trust manager try < SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); >catch (Exception e) < >// Now you can access an https URL without having the certificate in the truststore try < URL url = new URL("https://hostname/index.html"); >catch (MalformedURLException e)