How to set TLS version on apache HttpClient

120,145

Solution 1

The solution is:

SSLContext sslContext = SSLContexts.custom()
    .useTLS()
    .build();

SSLConnectionSocketFactory f = new SSLConnectionSocketFactory(
    sslContext,
    new String[]{"TLSv1", "TLSv1.1"},   
    null,
    BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

httpClient = HttpClients.custom()
    .setSSLSocketFactory(f)
    .build();

This requires org.apache.httpcomponents.httpclient 4.3.x though.

Solution 2

This is how I got it working on httpClient 4.5 (as per Olive Tree request):

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(AuthScope.ANY_HOST, 443),
        new UsernamePasswordCredentials(this.user, this.password));

SSLContext sslContext = SSLContexts.createDefault();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
        new String[]{"TLSv1", "TLSv1.1"},
        null,
        new NoopHostnameVerifier());

CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultCredentialsProvider(credsProvider)
        .setSSLSocketFactory(sslsf)
        .build();

return httpclient;

Solution 3

HttpClient-4.5,Use TLSv1.2 ,You must code like this:

 //Set the https use TLSv1.2
private static Registry<ConnectionSocketFactory> getRegistry() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext sslContext = SSLContexts.custom().build();
    SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
            new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    return RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.getSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();
}

public static void main(String... args) {
    try {
        //Set the https use TLSv1.2
        PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(getRegistry());
        clientConnectionManager.setMaxTotal(100);
        clientConnectionManager.setDefaultMaxPerRoute(20);
        HttpClient client = HttpClients.custom().setConnectionManager(clientConnectionManager).build();
        //Then you can do : client.execute(HttpGet or HttpPost);
    } catch (KeyManagementException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Solution 4

Using the HttpClientBuilder in HttpClient 4.5.x with a custom HttpClientConnectionManager with the defaults of HttpClientBuilder :

SSLConnectionSocketFactory sslConnectionSocketFactory = 
    new SSLConnectionSocketFactory(SSLContexts.createDefault(),          
                                   new String[] { "TLSv1.2" },                                            
                                   null, 
           SSLConnectionSocketFactory.getDefaultHostnameVerifier());

PoolingHttpClientConnectionManager poolingHttpClientConnectionManager =
    new PoolingHttpClientConnectionManager(
        RegistryBuilder.<ConnectionSocketFactory> create()
                       .register("http",
                                 PlainConnectionSocketFactory.getSocketFactory())
                       .register("https",
                                 sslConnectionSocketFactory)
                       .build());

// Customize the connection pool

CloseableHttpClient httpClient = HttpClientBuilder.create()
                                                  .setConnectionManager(poolingHttpClientConnectionManager)
                                                  .build()

Without a custom HttpClientConnectionManager :

SSLConnectionSocketFactory sslConnectionSocketFactory = 
    new SSLConnectionSocketFactory(SSLContexts.createDefault(),          
                                   new String[] { "TLSv1.2" },                                            
                                   null, 
           SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient httpClient = HttpClientBuilder.create()
                                                  .setSSLSocketFactory(sslConnectionSocketFactory)
                                                  .build()

Solution 5

For HttpClient-4.1 using TLSv1.2, code would go something like this:

        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, new SecureRandom());
        SSLSocketFactory sf = new SSLSocketFactory(sslContext);
        Scheme httpsScheme = new Scheme("https", 443, sf);
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(httpsScheme);
        ClientConnectionManager cm =  new        SingleClientConnManager(schemeRegistry);
        HttpClient client = new DefaultHttpClient(cm);

       // Use client to make the connection and get the results.
Share:
120,145

Related videos on Youtube

Oliveira
Author by

Oliveira

Updated on May 28, 2020

Comments

  • Oliveira
    Oliveira almost 4 years

    How can I change the supported TLS versions on my HttpClient?

    I'm doing:

    SSLContext sslContext = SSLContext.getInstance("TLSv1.1");
    sslContext.init(
        keymanagers.toArray(new KeyManager[keymanagers.size()]),
        null,
        null);
    
    SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext, new String[]{"TLSv1.1"}, null, null);
    Scheme scheme = new Scheme("https", 443, socketFactory);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(scheme);
    BasicClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry);
    httpClient = new DefaultHttpClient(cm);
    

    But when I check the created socket, it still says the supported protocols are TLSv1.0, TLSv1.1 and TLSv1.2.

    In reality I just want it to stop using TLSv1.2, for this specific HttpClient.

    • IgorGanapolsky
      IgorGanapolsky about 8 years
      What version of HttpClient are you trying to target?
  • douglaslps
    douglaslps almost 9 years
    It seems that this has been deprecated. Can you please update to reflect new httpClient versions?
  • Oliveira
    Oliveira almost 9 years
    I know. Unfortunately I didn't investigate too much on how to get it working with the new httpClient version, so I'm using an old version. But let me know if you get it working.
  • Anand Bhat
    Anand Bhat over 8 years
    Please note that the code snippet above uses NoopHostnameVerifier which essentially turns hostname verification off. In most cases, this is a very bad thing.
  • AntonioOtero
    AntonioOtero about 8 years
    Worked perfectly for me. I applied this solution to force calls to use TLSv1.2 since vendors like PayPay and UPS' API are now enforcing it. Java7 defaults to TLSv1, Java8 defaults to TLSv1.2 but I can't upgrade Java right now, so this post really helped me.
  • IgorGanapolsky
    IgorGanapolsky about 8 years
    What if I want to do something similar with httpclient 4.1.1?
  • Christopher Schultz
    Christopher Schultz almost 8 years
    @Skynet The technique should be valid, but the specific TLS protocols and cipher suites are generally dictated by the underlying JVM. So you'll have to check out the protocol support for Android < 4.1.
  • Gaurav Rawat
    Gaurav Rawat almost 8 years
    @Oliveira does setting system environment https.protocols=TLSv1,TLSv1.1 not achive the same result ?
  • Oliveira
    Oliveira almost 8 years
    @GauravRawat maybe. But then you change it for all the http clients, instead of just one.
  • Gaurav Rawat
    Gaurav Rawat almost 8 years
    That can still be done by using SSL connection socket factory.getSystemSocketFactory and be managed for the app easily, that shouldn't charge it for all but it's UpTo your choice anyways
  • Shrikant Thakare
    Shrikant Thakare over 7 years
    @AntonioOtero did you get it working with JDK7 ? I created client using above method.But I see that during SSL handshake (ClientHello) the protocol listed is TLSv1. I did set https.protocols also but no effect.Using httpclient-4.3.3.jar. Do you mean that this only changes the supported protocol on socket but the underlying SSL handshake is still controlled by JSSE API ? I mean Apache HttpClient does not implement any of the TLS protocol aspects. It relies on JSSE APIs to do TLS/SSL handshaking and to establish secure SSL sessions ?
  • AntonioOtero
    AntonioOtero over 7 years
    @ShrikantThakare I didn´t have those problems, I see TLSv1.2 listed. The only change I did to the code in this answer was to remove TLSv1.1 from the parameters of the factory, i.e. new String[]{"TLSv1.2"} Hope this helps
  • Christopher Schultz
    Christopher Schultz about 7 years
    @comeOnGetIt Java 6 mostly does not support anything higher than TLS 1.0 (stackoverflow.com/questions/33364100/…). Java 6 should be dead at this point, anyway.
  • Bertl
    Bertl almost 7 years
    Nope. Does NOT work server side, only in client side JVM Applets / Webstart.
  • jebeaudet
    jebeaudet over 6 years
    @Oliveira When you use HttpClientBuilder, this will work only if you enable systemProperties since it's off by default.
  • John Russell
    John Russell about 6 years
    Can one just use the org.apache.http.conn.ssl.DefaultHostnameVerifier ?
  • рüффп
    рüффп about 6 years
    It does not seem to work as well if you use the apache httpclient (tested with 3 and 4). I am not sure if these settings are really necessary if the other solutions are implemented.
  • Mohnish
    Mohnish almost 6 years
    Yes, if JDK makes the connection using URL#openConnection(), but these doesn't work with Apache HttpClient. Question is specifically tagged apache-httpclient-4.x
  • Horrorgoogle
    Horrorgoogle about 5 years
    what is useTLS()? what should be implementing in this?any idea?
  • Oliveira
    Oliveira about 5 years
  • JonnyJD
    JonnyJD almost 5 years
    This also works with Apache http client together with useSystemProperties()
  • JonnyJD
    JonnyJD almost 5 years
    -Dhttps.protocols also works with Apache http client together with useSystemProperties()
  • cviniciusm
    cviniciusm almost 4 years
    @ShrikantThakare which version and build of Java did you use, please?