How to ignore SSL certificate errors in Apache HttpClient 4.0
Asked Answered
F

25

166

How do I bypass invalid SSL certificate errors with Apache HttpClient 4.0?

Flaherty answered 24/4, 2010 at 3:59 Comment(9)
It should be noted that the answers to this question don't do more than what's asked: they let you ignore the error but don't fix the underlying problem (a bit like removing the batteries from a smoke alarm instead of putting out the fire). Certificates have a purpose in ensuring the security of the SSL/TLS connection, ignoring those errors introduces a vulnerability to MITM attack. Use test certificates instead of ignoring the error.Ricarda
Related to #1829275Osullivan
"like removing the batteries from a smoke alarm" You might give other developers the benefit of the doubt and assume they know what they're doing. Perhaps the motivation for this question is local testing and the OP wishes to run a quick test without going through the horrible amounts of Java boilerplate necessary to set up even a simple SSL environment. Maybe someone could just answer the question without going into a "holier than thou" lecture.Delius
I.e in our company internal JIRA server has some "windows security policy based cert" which is valid on Windows machines included in domain and not valid on other. I can't control this policy and still want to call JIRA REST API.Sememe
@Ricarda The inability to disable smoke detectors for a period of 30-60 minutes while dealing with a small kitchen fire shows an insane lack of insight into usage patterns by some legal official at some point that I feel borders on criminal. The fact that there is a concept of "removing batteries from a smoke alarm" proves this. I feel about the same level of anger about having to get certificates to work for a simple test that I know doesn't have security ramifications. The existence of this question proves this.Denature
@BillK Sure, don't get me wrong, I've disabled that sort of verification myself for simple tests once in a while. The real problem is that most people understand the why it's a problem with smoke alarms. That's not so much the case in software development: these lines of codes won't generate errors, and it's very easy for various project stakeholders (especially those who don't get near the code) to push for a product release without realising the consequences. Fixing things that don't cause errors is generally not a priority, especially when you have a deadline.Ricarda
@Ricarda Sounds like I agree--My point would be that to not recognize that this is an issue is a design flaw. If the designers were more aware of this issue they might have given us a command line -Dignore_certs_unsafe=true to disable cert checking completely. This is a pretty exact match to the fire alarm analogy where they should just have a button to disable it for 30 minutes instead of a law that it can't be disabled. Sometimes what is perceived as more security is actually less security in practice :)Denature
Hmm, and actually that might be a good way to implement this hack--setting a -D variable that you enable in your dev launch environment but never prod which would eliminate your concern about forgetting it.Denature
If you don't want it secure why are you using SSL at all?Consort
N
98

You need to create a SSLContext with your own TrustManager and create HTTPS scheme using this context. Here is the code,

SSLContext sslContext = SSLContext.getInstance("SSL");

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);

// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);
Nuri answered 24/4, 2010 at 4:32 Comment(12)
Say I don't want to buy valid SSL certificate for my site and just want to use it, this piece of code can help? How come I don't see any part where a URL is needed or exception handling is needed?Flaherty
As you can see the X509TrustManager doesn't check for anything and doesn't throw any exceptions so any cert is accepted.Nuri
Hmm, it's telling me that 'new SSLSocketFactory(ssslCont)' is expecting a KeyStore, not an SSLContext. Am I missing something?Momentary
For some reason the Jelatic and Heroku jetty and tomcat servers can't pick up on this code whereas AWS beanstalk's tomcat understands and runs it just fine ... strange.Puree
I get the error that an X509TrustManager can't be cast to a TrustManager.Psalms
Make sure that you import the correct packages, i.e. from org.apache.http.Gamophyllous
The way to create and configure an SSLContext is revised in 4.3: SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build();Wallace
Anyone know how to throw all this together using HttpClientBuilder?Responser
It works for me and SSLContext, TrustManager and X509TrustManager are all from package javax.net.sslFabulous
which version of HttpClient you're using ?Maldon
This technique is totally and utterly insecure. Do not use. Import the sever certificate into the client trust store, or gets the server certificate signed by a CA.Consort
Still getting Certificate for <....> doesn't match any of the....Devonadevondra
M
125

All of the other answers were either deprecated or didn't work for HttpClient 4.3.

Here is a way to allow all hostnames when building an http client.

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setHostnameVerifier(new AllowAllHostnameVerifier())
    .build();

Or if you are using version 4.4 or later, the updated call looks like this:

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .build();
Maryrosemarys answered 23/6, 2014 at 15:47 Comment(5)
Thanks for the answer, I would like to know from which package is HttpsClients as I'm using in Android compile("org.apache.httpcomponents:httpclient:4.3.4") but this class doesn't appear.Pignus
It's package is org.apache.http.impl.client.HttpClients .Maryrosemarys
This works around a host name mismatch (I assume), but it doesn't seem to work when the certificate isn't signed by a trusted authority.Centralize
@Centralize that's why it says it "allows all hostnames", trust issues require different configuration.Echopraxia
@eis, I was pointing out that this answer addresses the original question in certain cases but not others.Centralize
N
98

You need to create a SSLContext with your own TrustManager and create HTTPS scheme using this context. Here is the code,

SSLContext sslContext = SSLContext.getInstance("SSL");

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);

// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);
Nuri answered 24/4, 2010 at 4:32 Comment(12)
Say I don't want to buy valid SSL certificate for my site and just want to use it, this piece of code can help? How come I don't see any part where a URL is needed or exception handling is needed?Flaherty
As you can see the X509TrustManager doesn't check for anything and doesn't throw any exceptions so any cert is accepted.Nuri
Hmm, it's telling me that 'new SSLSocketFactory(ssslCont)' is expecting a KeyStore, not an SSLContext. Am I missing something?Momentary
For some reason the Jelatic and Heroku jetty and tomcat servers can't pick up on this code whereas AWS beanstalk's tomcat understands and runs it just fine ... strange.Puree
I get the error that an X509TrustManager can't be cast to a TrustManager.Psalms
Make sure that you import the correct packages, i.e. from org.apache.http.Gamophyllous
The way to create and configure an SSLContext is revised in 4.3: SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build();Wallace
Anyone know how to throw all this together using HttpClientBuilder?Responser
It works for me and SSLContext, TrustManager and X509TrustManager are all from package javax.net.sslFabulous
which version of HttpClient you're using ?Maldon
This technique is totally and utterly insecure. Do not use. Import the sever certificate into the client trust store, or gets the server certificate signed by a CA.Consort
Still getting Certificate for <....> doesn't match any of the....Devonadevondra
E
84

Apache HttpClient 4.5.5

HttpClient httpClient = HttpClients
            .custom()
            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
            .build();

No deprecated API has been used.

Simple verifiable test case:

package org.apache.http.client.test;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class ApacheHttpClientTest {

    private HttpClient httpClient;

    @Before
    public void initClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        httpClient = HttpClients
                .custom()
                .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }

    @Test
    public void apacheHttpClient455Test() throws IOException {
        executeRequestAndVerifyStatusIsOk("https://expired.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://wrong.host.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://self-signed.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://untrusted-root.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://revoked.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://pinning-test.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://sha1-intermediate.badssl.com");
    }

    private void executeRequestAndVerifyStatusIsOk(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        assert statusCode == 200;
    }
}
Eridanus answered 10/5, 2018 at 13:50 Comment(5)
Thank you! Just change TrustAllStrategy.INSTANCE with TrustSelfSignedStrategy.INSTANCE in this answer.Vlissingen
This did not work for me. 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 targetAuscultation
@Auscultation I don't find TrustAllStrategy.INSTANCE, but I try implement it by myself: new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build() and it has worked.Shaunna
.setSSLContext() in the 4.5.6 apache dependency actually throws and error? Changing it to .setSslContext() made the error go away?? Unless they changed it in 4.5.6, it should be .setSslContext() with a lowercase "Ssl"Paddock
This answer worked but not without @SvichkarevAnatoly 's comment. Thanks to both!!Salaried
H
63

Just had to do this with the newer HttpClient 4.5 and it seems like they've deprecated a few things since 4.4 so here's the snippet that works for me and uses the most recent API:

final SSLContext sslContext = new SSLContextBuilder()
        .loadTrustMaterial(null, (x509CertChain, authType) -> true)
        .build();

return HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .setConnectionManager(
                new PoolingHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.INSTANCE)
                                .register("https", new SSLConnectionSocketFactory(sslContext,
                                        NoopHostnameVerifier.INSTANCE))
                                .build()
                ))
        .build();
Hallett answered 21/7, 2016 at 16:0 Comment(3)
Worked for me also for httpclient 4.5.2Cacophonous
this one is up-to-date for HttpClient 4.5Bechuanaland
Answers the question and valid till in 2023 with the latest version of HttpClientFluffy
W
34

Just for the record, there is a much simpler way to accomplish the same with HttpClient 4.1

    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

        public boolean isTrusted(
                final X509Certificate[] chain, String authType) throws CertificateException {
            // Oh, I am easy...
            return true;
        }

    });
Whaleback answered 1/5, 2012 at 16:9 Comment(4)
Are you missing some code in this sample? Maybe a call to httpClient.set...?Osullivan
httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, sslsf));Schoolman
SSLSocketFactory is deprecated in HttpClient 4.3Powwow
If using Java 8, you can even new SSLSocketFactory((chain, authType) -> true);Imbroglio
E
29

For the record, tested with httpclient 4.3.6 and compatible with Executor of fluent api:

CloseableHttpClient httpClient = HttpClients.custom().
                    setHostnameVerifier(new AllowAllHostnameVerifier()).
                    setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
                    {
                        public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
                        {
                            return true;
                        }
                    }).build()).build();
Estevan answered 18/12, 2014 at 22:18 Comment(3)
For HttpClient 4.4 upwards, you have to do this -- and may also need to create an SSLConnectionSocketFactory using that SSLContext, and define this in a Registry<ConnectionSocketFactory>, if you're going to create a PoolingHttpClientConnectionManager. The other answers are more popular, but don't work at HttpClient 4.4.Shipment
Works exactly like this with httpclient-4.3.5.jar.Ne
works with httpclient 4.3.2Dressage
S
18

For Apache HttpClient 4.4:

HttpClientBuilder b = HttpClientBuilder.create();

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        return true;
    }
}).build();
b.setSslcontext( sslContext);

// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", sslSocketFactory)
        .build();

// allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);

HttpClient client = b.build();

This is extracted from our actual working implementation.

The other answers are popular, but for HttpClient 4.4 they don't work. I spent hours trying & exhausting possibilities, but there seems to have been extremely major API change & relocation at 4.4.

See also a slightly fuller explanation at: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Hope that helps!

Shipment answered 4/3, 2015 at 5:21 Comment(0)
R
14

If all you want to do is get rid of invalid hostname errors you can just do:

HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
    .getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
Reichenberg answered 12/5, 2011 at 13:50 Comment(1)
The sf.setHostnameVerifier method has been deprecated as of 4.1. The alternative is to use one of the constructors. For example: SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);Cammie
G
9

We are using HTTPClient 4.3.5 and we tried almost all solutions exist on the stackoverflow but nothing, After thinking and figuring out the problem, we come to the following code which works perfectly, just add it before creating HttpClient instance.

some method to call when making post requests....

SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            return true;
        }
    });

    SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
    HttpPost postRequest = new HttpPost(url);

continue your request in the normal form

Gabon answered 3/4, 2015 at 15:31 Comment(0)
J
8

With fluent 4.5.2 i had to make the following modification to make it work.

try {
    TrustManager[] trustAllCerts = new TrustManager[] {
       new X509TrustManager() {
    public java.security.cert.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, trustAllCerts, new SecureRandom());
    CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSslcontext(sc).build();

    String output = Executor.newInstance(httpClient).execute(Request.Get("https://127.0.0.1:3000/something")
                                      .connectTimeout(1000)
                                      .socketTimeout(1000)).returnContent().asString();
    } catch (Exception e) {
    }
Jumpoff answered 18/9, 2016 at 16:43 Comment(1)
This is the only solution that worked for me. I tried the above solutions for 4.3 and 4.4 before upgrading to 4.5 and trying this.Portion
V
6

This is how I did it -

  1. Create my own MockSSLSocketFactory (Class attached below)
  2. Use it to initialise DefaultHttpClient. Proxy settings need to be provided if a proxy is used.

Initialising DefaultHTTPClient -

SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme("https", 443, new MockSSLSocketFactory()));
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);

    DefaultHttpClient httpclient = new DefaultHttpClient(cm);

Mock SSL Factory -

public class MockSSLSocketFactory extends SSLSocketFactory {

public MockSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(trustStrategy, hostnameVerifier);
}

private static final X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {
    @Override
    public void verify(String host, SSLSocket ssl) throws IOException {
        // Do nothing
    }

    @Override
    public void verify(String host, X509Certificate cert) throws SSLException {
        //Do nothing
    }

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
        //Do nothing
    }

    @Override
    public boolean verify(String s, SSLSession sslSession) {
        return true; 
    }
};

private static final TrustStrategy trustStrategy = new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
};
}

If behind a proxy, need to do this -

HttpParams params = new BasicHttpParams();
    params.setParameter(AuthPNames.PROXY_AUTH_PREF, getClientAuthPrefs());

DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);

httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(proxyHost, proxyPort),
                        new UsernamePasswordCredentials(proxyUser, proxyPass));
Vitale answered 16/8, 2012 at 13:34 Comment(1)
It would help if you included the imports in the future. There are two different classes.Submerse
B
5

In extension to ZZ Coder's answer it will be nice to override the hostnameverifier.

// ...
SSLSocketFactory sf = new SSLSocketFactory (sslContext);
sf.setHostnameVerifier(new X509HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }

    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
    }

    public void verify(String host, X509Certificate cert) throws SSLException {
    }

    public void verify(String host, SSLSocket ssl) throws IOException {
    }
});
// ...
Balaam answered 8/10, 2010 at 20:28 Comment(2)
You can achieve the same by just doing sf.setHostnameVerifier(new AllowAllHostnameVerifier());Betancourt
The sf.setHostnameVerifier has been deprecated as of 4.1. The alternative is to use one of the constructors. For example: SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);Cammie
U
5

Tested with HttpClient 4.5.5 with Fluent API

final SSLContext sslContext = new SSLContextBuilder()
    .loadTrustMaterial(null, (x509CertChain, authType) -> true).build();

CloseableHttpClient httpClient = HttpClients.custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .setSSLContext(sslContext).build();

String result = Executor.newInstance(httpClient)
    .execute(Request.Get("https://localhost:8080/someapi")
    .connectTimeout(1000).socketTimeout(1000))
    .returnContent().asString();
Undying answered 5/4, 2018 at 9:21 Comment(0)
C
4
        DefaultHttpClient httpclient = new DefaultHttpClient();

    SSLContext sslContext;
    try {
        sslContext = SSLContext.getInstance("SSL");

        // set up a TrustManager that trusts everything
        try {
            sslContext.init(null,
                    new TrustManager[] { new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            log.debug("getAcceptedIssuers =============");
                            return null;
                        }

                        public void checkClientTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkClientTrusted =============");
                        }

                        public void checkServerTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkServerTrusted =============");
                        }
                    } }, new SecureRandom());
        } catch (KeyManagementException e) {
        }
         SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
         ClientConnectionManager ccm = this.httpclient.getConnectionManager();
         SchemeRegistry sr = ccm.getSchemeRegistry();
         sr.register(new Scheme("https", 443, ssf));            
    } catch (Exception e) {
        log.error(e.getMessage(),e);
    }
Clapboard answered 23/7, 2012 at 14:25 Comment(0)
G
4

To accept all certificates in HttpClient 4.4.x you can use the following one liner when creating the httpClient:

httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build()).build();
Groyne answered 15/4, 2015 at 13:46 Comment(2)
I am getting this: Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present?Maldon
How to allow connections to SSL sites without certs in HttpClient API or in RestClient API ?Maldon
T
3

Tested on 4.5.4:

            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build();

            CloseableHttpClient httpClient = HttpClients
                    .custom()
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setSSLContext(sslContext)
                    .build();
Tarnation answered 14/12, 2017 at 3:24 Comment(0)
K
3

Below code works with 4.5.5

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

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

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

class HttpsSSLClient {


    public static CloseableHttpClient createSSLInsecureClient() {
        SSLContext sslcontext = createSSLContext();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new HostnameVerifier() {

            @Override
            public boolean verify(String paramString, SSLSession paramSSLSession) {
                return true;
            }
        });
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        return httpclient;
    }


    private static SSLContext createSSLContext() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[] {new TrustAnyTrustManager()}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslcontext;
    }


    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }

}
public class TestMe {


    public static void main(String[] args) throws IOException {
        CloseableHttpClient client = HttpsSSLClient.createSSLInsecureClient();

        CloseableHttpResponse res = client.execute(new HttpGet("https://wrong.host.badssl.com/"));
        System.out.println(EntityUtils.toString(res.getEntity()));
    }
}

Output from code is

Code

Output on browser is

Bad SSL

The pom used is below

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tarun</groupId>
    <artifactId>testing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

</dependencies>
</project>
Kilgore answered 8/5, 2018 at 14:58 Comment(0)
P
2

a full working version for Apache HttpClient 4.1.3 (based on oleg's code above, but it still needed an allow_all_hostname_verifier on my system):

private static HttpClient trustEveryoneSslHttpClient() {
    try {
        SchemeRegistry registry = new SchemeRegistry();

        SSLSocketFactory socketFactory = new SSLSocketFactory(new TrustStrategy() {

            public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
                // Oh, I am easy...
                return true;
            }

        }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        registry.register(new Scheme("https", 443, socketFactory));
        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
        DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
        return client;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

Note I'm re-throwing all exceptions because really, there's not much I can do if any of this fails in a real system!

Priapus answered 31/5, 2012 at 5:49 Comment(0)
H
2

If you are using the fluent API, you need to set it up via the Executor:

Executor.unregisterScheme("https");
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext,
                                  SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Executor.registerScheme(new Scheme("https", 443, sslSocketFactory));

... where sslContext is the SSLContext created as shown in the ZZ Coder's answer.

After that, you can do your http requests as:

String responseAsString = Request.Get("https://192.168.1.0/whatever.json")
                         .execute().getContent().asString();

Note: tested with HttpClient 4.2

Hintze answered 4/7, 2013 at 13:49 Comment(1)
Unfortunately deprecated in 4.3: "Deprecated. (4.3) do not use."Estevan
H
2

Tested with 4.3.3

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
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.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class AccessProtectedResource {

public static void main(String[] args) throws Exception {

    // Trust all certs
    SSLContext sslcontext = buildSSLContext();

    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://yoururl");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            for (Header header : response.getAllHeaders()) {
                System.out.println(header);
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

private static SSLContext buildSSLContext()
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException {
    SSLContext sslcontext = SSLContexts.custom()
            .setSecureRandom(new SecureRandom())
            .loadTrustMaterial(null, new TrustStrategy() {

                public boolean isTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    return true;
                }
            })
            .build();
    return sslcontext;
}

}

Herrington answered 8/7, 2014 at 6:23 Comment(1)
How to set values in Headers if I wanted to do that ?Maldon
B
0

If you encountered this problem when using AmazonS3Client, which embeds Apache HttpClient 4.1, you simply need to define a system property like this so that the SSL cert checker is relaxed:

-Dcom.amazonaws.sdk.disableCertChecking=true

Mischief managed

Bonaparte answered 24/9, 2012 at 22:0 Comment(0)
S
0

fwiw, an example using "RestEasy" implementation of JAX-RS 2.x to build a special "trust all" client...

    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.security.GeneralSecurityException;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.Arrays;
    import javax.ejb.Stateless;
    import javax.net.ssl.SSLContext;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.HttpClientConnectionManager;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.jboss.resteasy.client.jaxrs.ResteasyClient;
    import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
    import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
    import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
    import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.ssl.SSLContexts;

    @Stateless
    @Path("/postservice")
    public class PostService {

        private static final Logger LOG = LogManager.getLogger("PostService");

        public PostService() {
        }

        @GET
        @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
        public PostRespDTO get() throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException, IOException, GeneralSecurityException {

            //...object passed to the POST method...
            PostDTO requestObject = new PostDTO();
            requestObject.setEntryAList(new ArrayList<>(Arrays.asList("ITEM0000A", "ITEM0000B", "ITEM0000C")));
            requestObject.setEntryBList(new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));

            //...build special "trust all" client to call POST method...
            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(createTrustAllClient());

            ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
            ResteasyWebTarget target = client.target("https://localhost:7002/postRespWS").path("postrespservice");
            Response response = target.request().accept(MediaType.APPLICATION_JSON).post(Entity.entity(requestObject, MediaType.APPLICATION_JSON));

            //...object returned from the POST method...
            PostRespDTO responseObject = response.readEntity(PostRespDTO.class);

            response.close();

            return responseObject;
        }


        //...get special "trust all" client...
        private static CloseableHttpClient createTrustAllClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, TRUSTALLCERTS).useProtocol("TLS").build();
            HttpClientBuilder builder = HttpClientBuilder.create();
            NoopHostnameVerifier noop = new NoopHostnameVerifier();
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, noop);
            builder.setSSLSocketFactory(sslConnectionSocketFactory);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
            HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
            builder.setConnectionManager(ccm);

            return builder.build();
        }


        private static final TrustStrategy TRUSTALLCERTS = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
                return true;
            }
        };
    }

related Maven dependencies

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>jaxrs-api</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency> 
Selie answered 4/2, 2016 at 14:39 Comment(0)
I
0

Careful with the use of SSLConnectionSocketFactory. This was noted with Apache HttpClient v4.5.x

Caused by: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <somedomain.org> doesn't match any of the subject alternative names: [cert-used-in-2-way-tls.org, www.cert-used-in-2-way-tls.org]

The following code still yielded above exception:

        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        inputStream = new FileInputStream(certificatePath);

        keyStore.load(inputStream, certificatePassword.toCharArray());

        SSLContext sslContext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, certificatePassword.toCharArray())
                .build();

        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext); //don't do this

        client = HttpClients.custom()
                    .setSSLSocketFactory(socketFactory) //don't do this
                    //.setSSLContext(sslContext) //do this instead
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .build();

The following worked for me instead:

             //same code as above, but not using the SSLConnectionSocketFactory 
             client = HttpClients.custom()
                    .setSSLContext(sslContext) //do this instead
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .build(); 
Inflight answered 10/5, 2023 at 22:1 Comment(0)
B
-1

If you are using Apache httpClient 4.5.x then try this:

public static void main(String... args)  {

    try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
        HttpGet httpget = new HttpGet("https://example.com");
        System.out.println("Executing request " + httpget.getRequestLine());

        httpclient.execute(httpget);
        System.out.println("----------------------------------------");
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

    // use the TrustSelfSignedStrategy to allow Self Signed Certificates
    SSLContext sslContext = SSLContextBuilder
            .create()
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    // we can optionally disable hostname verification. 
    // if you don't want to further weaken the security, you don't have to include this.
    HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

    // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
    // and allow all hosts verifier.
    SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

    // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
    return HttpClients
            .custom()
            .setSSLSocketFactory(connectionFactory)
            .build();
}
Bo answered 4/5, 2018 at 18:9 Comment(0)
S
-1

For java.net.http.HttpClient


Imports

import java.net.http.HttpClient;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

Usage

    try {
        sslContext = SSLContexts.custom()
                .loadTrustMaterial(null, (chain, authType) -> true)
                .build();
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        
    HttpClient httpClient = HttpClient.newBuilder().sslContext(sslContext).build();

Tested on Elasticsearch 8.1.3 as a Maven plugin

Salaried answered 29/3, 2023 at 11:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.