Попытка переопределить версию TLS [duplicate]

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
27
задан Oliveira 8 February 2015 в 08:50
поделиться

9 ответов

Решение:

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

Для этого требуется org.apache.httpcomponents.httpclient 4.3.x.

32
ответ дан Oliveira 19 August 2018 в 06:56
поделиться
  • 1
    Похоже, что это устарело. Можете ли вы обновить, чтобы отобразить новые версии httpClient? – douglaslps 7 July 2015 в 19:10
  • 2
    Я знаю. К сожалению, я не слишком разбирался в том, как заставить его работать с новой версией httpClient, поэтому я использую старую версию. Но дайте мне знать, если вы заработаете. – Oliveira 8 July 2015 в 12:45
  • 3
    Отлично работал для меня. Я применил это решение, чтобы заставить вызовы использовать TLSv1.2, поскольку такие поставщики, как API PayPay и UPS, теперь применяют его. Java7 по умолчанию имеет TLSv1, Java8 по умолчанию - TLSv1.2, но я не могу обновить Java прямо сейчас, поэтому этот пост действительно помог мне. – AntonioOtero 10 March 2016 в 18:30
  • 4
    Что делать, если я хочу сделать что-то подобное с httpclient 4.1.1? – Igor Ganapolsky 20 April 2016 в 16:33
  • 5
    @Oliveira делает настройку системной среды https.protocols = TLSv1, TLSv1.1 не достигает того же результата? – Gaurav Rawat 13 July 2016 в 23:03

Если вы используете httpclient 4.2, вам нужно написать небольшой бит дополнительного кода. Я хотел иметь возможность настраивать как «протоколы с поддержкой TLS» (например, TLSv1.1 в частности, так и не TLSv1, TLSv1.2), а также шифровые номера .

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

Тогда:

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

Возможно, вы сможете сделать это с чуть меньшим количеством кода, но я в основном копирую / вставляю из настраиваемого компонента, где имеет смысл создавать объекты в путь, показанный выше.

2
ответ дан Christopher Schultz 19 August 2018 в 06:56
поделиться
  • 1
    Будет ли это работать с httpclient 4.1? – Igor Ganapolsky 20 April 2016 в 16:36
  • 2
    @IgorGanapolsky API выглядит хорошо. Вы могли бы просто попробовать это;) – Christopher Schultz 21 April 2016 в 17:09
  • 3
    Будет ли это работать с версиями Android ниже 4.1? – Skynet 29 June 2016 в 07:38
  • 4
    @Skynet. Техника должна быть действительной, но конкретные протоколы TLS и комплекты шифров обычно продиктованы базовой JVM. Поэтому вам нужно будет проверить поддержку протокола для Android & lt; 4.1. – Christopher Schultz 29 June 2016 в 15:32
  • 5
    Не работает с java 6 – comeOnGetIt 11 May 2017 в 14:52

Если у вас есть ссылка класса javax.net.ssl.SSLSocket в вашем коде, вы можете установить разрешенные TLS-протоколы вызовом 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);
}
2
ответ дан David Tonhofer 19 August 2018 в 06:56
поделиться

Вот как я работал над httpClient 4.5 (в соответствии с запросом оливкового дерева):

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;
12
ответ дан douglaslps 19 August 2018 в 06:56
поделиться
  • 1
    Обратите внимание, что в приведенном выше фрагменте кода используется NoopHostnameVerifier, который по существу отключает проверку имени хоста. В большинстве случаев это очень плохо. – Anand Bhat 15 September 2015 в 15:12
  • 2
    Можно ли просто использовать org.apache.http.conn.ssl.DefaultHostnameVerifier? – John Russell 20 February 2018 в 20:45

Использование -Dhttps.protocols = TLSv1.2 Аргумент JVM не работал для меня. Работает следующий код

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

Используйте следующий аргумент JVM для проверки

-Djavax.net.debug=all
0
ответ дан duvo 19 August 2018 в 06:56
поделиться

Используя HttpClientBuilder в HttpClient 4.5.x с пользовательским HttpClientConnectionManager со значениями по умолчанию 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()

Без пользовательского HttpClientConnectionManager:

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

CloseableHttpClient httpClient = HttpClientBuilder.create()
                                                  .setSSLSocketFactory(sslConnectionSocketFactory)
                                                  .build()
2
ответ дан jebeaudet 19 August 2018 в 06:56
поделиться

Вы можете просто указать следующее свойство -Dhttps.protocols = TLSv1.1, TLSv1.2 на вашем сервере, который настраивает JVM, чтобы указать, какая версия протокола TLS должна использоваться во всех https-соединениях с клиента.

0
ответ дан Sachin Kumar 19 August 2018 в 06:56
поделиться
  • 1
    Неа. НЕ работает на стороне сервера, только на стороне клиента JVM Applets / Webstart. – Bertl 30 June 2017 в 08:18
  • 2
    Это не работает, если вы используете apache httpclient (проверены с 3 и 4). Я не уверен, действительно ли эти настройки необходимы, если другие решения реализованы. – рüффп 27 February 2018 в 14:23
  • 3
    Да, если JDK делает соединение с помощью URL#openConnection(), но они не работают с Apache HttpClient. Вопрос специально помечен apache-httpclient-4.x – Mohnish 6 June 2018 в 16:07

HttpClient-4.5, Use TLSv1.2, вы должны закодировать следующим образом:

 //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();
    }
}
6
ответ дан sfxm 19 August 2018 в 06:56
поделиться

Для HttpClient-4.1 с использованием TLSv1.2 код будет выглядеть примерно так:

        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 19 August 2018 в 06:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: