wake-up-neo.net

So legen Sie die TLS-Version für Apache HttpClient fest

Wie kann ich die unterstützten TLS-Versionen auf meinem HttpClient ändern?

Ich mache:

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

Wenn ich jedoch das erstellte Socket überprüfe, werden immer noch die unterstützten Protokolle TLSv1.0, TLSv1.1 und TLSv1.2 unterstützt.

In Wirklichkeit möchte ich nur, dass TLSv1.2 für diesen spezifischen HttpClient nicht mehr verwendet wird.

29
Oliveira

Die Lösung ist:

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

Dies erfordert jedoch org.Apache.httpcomponents.httpclient 4.3.x.

33
Oliveira

So habe ich es auf httpClient 4.5 (gemäß Olive Tree-Anfrage) zum Laufen gebracht:

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;
13
douglaslps

HttpClient-4.5, TLSv1.2 verwenden, Sie müssen den folgenden Code eingeben:

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

Für HttpClient-4.1 mit TLSv1.2 würde der Code in etwa folgendermaßen aussehen:

        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.
5
user2122524

Verwenden der HttpClientBuilder in HttpClient 4.5.x mit einer benutzerdefinierten HttpClientConnectionManager mit den Standardeinstellungen von 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()

Ohne benutzerdefinierte HttpClientConnectionManager

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

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

Wenn Sie httpclient 4.2 verwenden, müssen Sie ein wenig zusätzlichen Code schreiben. Ich wollte in der Lage sein, sowohl die "TLS-fähigen Protokolle" (z. B. TLSv1.1 und weder TLSv1 noch TLSv1.2) als auch die Cipher Suites anzupassen.

public class CustomizedSSLSocketFactory
    extends SSLSocketFactory
{
    private String[] _tlsProtocols;
    private String[] _tlsCipherSuites;

    public CustomizedSSLSocketFactory(SSLContext sslContext,
                                      X509HostnameVerifier hostnameVerifier,
                                      String[] tlsProtocols,
                                      String[] cipherSuites)
    {
        super(sslContext, hostnameVerifier);

        if(null != tlsProtocols)
            _tlsProtocols = tlsProtocols;
        if(null != cipherSuites)
            _tlsCipherSuites = cipherSuites;
    }

    @Override
    protected void prepareSocket(SSLSocket socket)
    {
        // Enforce client-specified protocols or cipher suites
        if(null != _tlsProtocols)
            socket.setEnabledProtocols(_tlsProtocols);

        if(null != _tlsCipherSuites)
            socket.setEnabledCipherSuites(_tlsCipherSuites);
    }
}

Dann:

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

    sslContext.init(null, getTrustManagers(), new SecureRandom());

    // NOTE: not javax.net.SSLSocketFactory
    SSLSocketFactory sf = new CustomizedSSLSocketFactory(sslContext,
                                                         null,
                                                         [TLS protocols],
                                                         [TLS cipher suites]);

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

    ConnectionManager cm = new BasicClientConnectionManager(schemeRegistry);

    HttpClient client = new DefaultHttpClient(cmgr);
    ...

Möglicherweise können Sie dies mit etwas weniger Code tun, aber ich habe meistens eine benutzerdefinierte Komponente kopiert/eingefügt, bei der es sinnvoll war, die Objekte wie oben gezeigt aufzubauen.

2

Wenn Sie in Ihrem Code eine javax.net.ssl.SSLSocket -Klassenreferenz haben, können Sie die aktivierten TLS-Protokolle durch einen Aufruf an SSLSocket.setEnabledProtocols () festlegen:

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);
}
2
IgorGanapolsky

Das Verwenden des -Dhttps.protocols = TLSv1.2-JVM-Arguments funktionierte für mich nicht. Was funktioniert hat, ist der folgende Code

RequestConfig.Builder requestBuilder = RequestConfig.custom();
//other configuration, for example
requestBuilder = requestBuilder.setConnectTimeout(1000);

SSLContext sslContext = SSLContextBuilder.create().useProtocol("TLSv1.2").build();

HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultRequestConfig(requestBuilder.build());
builder.setProxy(new HttpHost("your.proxy.com", 3333)); //if you have proxy
builder.setSSLContext(sslContext);

HttpClient client = builder.build();

Verwenden Sie zur Überprüfung das folgende JVM-Argument

-Djavax.net.debug=all
0
duvo

Sie können einfach die folgende Eigenschaft -Dhttps.protocols = TLSv1.1, TLSv1.2 auf Ihrem Server angeben, wodurch die JVM konfiguriert wird, um anzugeben, welche TLS-Protokollversion bei allen https-Verbindungen vom Client verwendet werden soll.

0
Sachin Kumar

Da dies nur in Kommentaren versteckt auftauchte, war es schwierig, eine Lösung zu finden:

Sie können Java -Dhttps.protocols=TLSv1,TLSv1.1, aber Sie müssen auch seSystemProperties () verwenden

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

Wir verwenden dieses Setup jetzt in unserem System, da wir dies nur für eine bestimmte Verwendung des Codes einstellen können. In unserem Fall läuft immer noch etwas Java 7 und ein API-Endpunkt hat TLSv1 nicht zugelassen, daher verwenden wir Java -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2, um aktuelle TLS-Versionen zu aktivieren. Vielen Dank an @jebeaudet für den Hinweis in diese Richtung.

0
JonnyJD