java - Como definir a versão TLS no apache HttpClient




ssl apache-httpclient-4.x (7)

A solução é:

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();

Isso requer o org.apache.httpcomponents.httpclient 4.3.x.

Como posso alterar as versões TLS suportadas no meu HttpClient?

Estou fazendo:

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);

Mas quando eu checo o soquete criado, ele ainda diz que os protocolos suportados são TLSv1.0, TLSv1.1 e TLSv1.2.

Na realidade, eu só quero que ele pare de usar o TLSv1.2, para este HttpClient específico.


Como isso só apareceu escondido nos comentários, difícil de encontrar como solução:

Você pode usar java -Dhttps.protocols=TLSv1,TLSv1.1 , mas também precisa usar useSystemProperties()

client = HttpClientBuilder.create().useSystemProperties();

Agora usamos essa configuração em nosso sistema, pois isso nos permite definir isso apenas para o uso do código. No nosso caso, ainda temos o Java 7 em execução e um ponto de extremidade da API não permitido TLSv1, portanto, usamos java -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 para ativar as versões atuais do TLS. Obrigado @jebeaudet por apontar nessa direção.


HttpClient-4.5, use TLSv1.2, você deve codificar assim:

 //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();
    }
}

Para o HttpClient-4.1 usando TLSv1.2, o código seria algo como isto:

        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.

Se você tiver uma referência de classe javax.net.ssl.SSLSocket em seu código, poderá configurar os protocolos TLS ativados por uma chamada para SSLSocket.setEnabledProtocols() :

import javax.net.ssl.*;
import java.net.*; 
...
Socket socket = SSLSocketFactory.getDefault().createSocket();
...
if (socket instanceof SSLSocket) {
   // "TLSv1.0" gives IllegalArgumentException in Java 8
   String[] protos = {"TLSv1.2", "TLSv1.1"}
   ((SSLSocket)socket).setEnabledProtocols(protos);
}

Usando o HttpClientBuilder no HttpClient 4.5.x com um HttpClientConnectionManager personalizado com os padrões do 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()

Sem um HttpClientConnectionManager personalizado:

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

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

Você pode apenas especificar a seguinte propriedade -Dhttps.protocols = TLSv1.1, TLSv1.2 no servidor que configura a JVM para especificar qual versão do protocolo TLS deve ser usada durante todas as conexões https do cliente.







apache-httpclient-4.x