Как обрабатывать недопустимые SSL-сертификаты с помощью Apache HttpClient?

Я знаю, есть много разных вопросов и так много ответов об этой проблеме... Но я не могу понять...

У меня есть: ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 установлен "как есть" от off. по донесению Мне нужно подключиться к некоторому сайту через HTTPS. Для этого я использую Apache HttpClient.

Из учебника я читал:

"Как только вы правильно установили JSSE, безопасная HTTP-связь через SSL должна быть как
 простое как обычное HTTP-сообщение ". И еще один пример:

HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.verisign.com/"); 
try { 
  httpclient.executeMethod(httpget);
  System.out.println(httpget.getStatusLine());
} finally {
  httpget.releaseConnection();
}

В настоящее время я пишу это:

HttpClient client = new HttpClient();

HttpMethod get = new GetMethod("https://mms.nw.ru");
//get.setDoAuthentication(true);

try {
    int status = client.executeMethod(get);
    System.out.println(status);

    BufferedInputStream is = new BufferedInputStream(get.getResponseBodyAsStream());
    int r=0;byte[] buf = new byte[10];
    while((r = is.read(buf)) > 0) {
        System.out.write(buf,0,r);
    }

} catch(Exception ex) {
    ex.printStackTrace();
}

В результате у меня есть набор ошибок:

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 target
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1627)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:204)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:198)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:994)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:142)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:533)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:471)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:904)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1132)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:643)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:78)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:828)
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2116)
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
        at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
        at simpleapachehttp.Main.main(Main.java:41)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:302)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:205)
        at sun.security.validator.Validator.validate(Validator.java:235)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:973)
        ... 17 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:191)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:297)
        ... 23 more

Что мне делать, чтобы создать простейшее SSL-соединение? (Возможно, без KeyManager и Trust Manager и т.д.).

Ответ 1

https://mms.nw.ru использует самозаверяющий сертификат, который, очевидно, не содержится в наборе доверительных менеджеров по умолчанию.

Вам нужно выполнить одно из следующих действий:

  • Настройте SSLContext с помощью TrustManager, который принимает любой сертификат (см. ниже)

  • Настройте SSLContext с соответствующим хранилищем доверия, которое включает ваш сертификат

  • Добавьте сертификат для этого сайта в хранилище доверия java по умолчанию.

Вот пример программы, которая создает (в основном бесполезный) SSL-контекст, который принимает любой сертификат:

import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLTest {

    public static void main(String [] args) throws Exception {
        // configure the SSLContext with a TrustManager
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        URL url = new URL("https://mms.nw.ru");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        System.out.println(conn.getResponseCode());
        conn.disconnect();
    }

    private static class DefaultTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
}

Ответ 2

https://mms.nw.ru, вероятно, использует сертификат, не выданный центром сертификации. Следовательно, вам нужно добавить сертификат в хранилище доверенных Java-ключей, как описано в не удалось найти допустимый путь сертификации для запрошенной цели:

При работе с клиентом, который работает с сервером с поддержкой SSL, запущенным в https, вы можете получить ошибку "не удалось найти действительную сертификацию путь к запрашиваемой цели", если сертификат сервера не выдается центра сертификации, но подписанный или выпущенный частной CMS.

Не паникуйте. Все, что вам нужно сделать, это добавьте сертификат сервера на свой доверенное хранилище ключей Java, если ваш клиент написан на Java. Вы, возможно интересно, как будто вы не можете получить доступ машина, на которой находится сервер установлен. Существует простая программа могу помочь тебе. Загрузите Java программы и запустить

% java InstallCert _web_site_hostname_

Эта программа открыла соединение с указанного хоста и запустил SSL рукопожатие. Он напечатал исключение трассировка ошибки, которая произошла и показывает вам сертификаты, используемые сервер. Теперь вам предлагается добавить сертификат на ваш доверенный KeyStore.

Если вы передумали, введите "Д". Если вы действительно хотите добавить сертификат, введите "1" или другое номера для добавления других сертификатов, даже сертификат CA, но вы обычно не хочу этого делать. Как только вы сделал ваш выбор, программа будет отобразить полный сертификат и затем добавили его в Java KeyStore с именем 'jssecacerts' в текущем каталог.

Чтобы использовать его в своей программе, настроить JSSE для использования в качестве доверия хранить или копировать его в свой $JAVA_HOME/jre/lib/каталог безопасности. Если вы хотите, чтобы все приложения Java признать сертификат доверенным а не только JSSE, вы также можете перезапишите файл cacerts в этом каталог.

После всего этого JSSE сможет завершите рукопожатие с хозяином, которые вы можете проверить, запустив снова.

Чтобы получить более подробную информацию, вы можете проверить Leeland blog Больше не удается найти действительный путь сертификации целевой '

Ответ 3

В дополнение к правильному ответу Pascal Thivent другим способом является сохранение сертификата из Firefox (Просмотреть сертификат → Подробности → экспорт) или openssl s_client и импортировать его в хранилище доверия.

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

Чтобы импортировать его в хранилище доверия, используйте:

keytool -importcert -keystore truststore.jks -file servercert.pem

По умолчанию хранилище доверия по умолчанию должно быть lib/security/cacerts, а его пароль должен быть changeit, см. Справочное руководство JSSE.

Если вы не хотите разрешать этот сертификат глобально, но только для этих подключений, возможно создать для него SSLContext:

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../truststore.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

Затем вам нужно настроить его для Apache HTTP Client 3.x, выполнив его, если его SecureProtocolSocketFactory использовать этот SSLContext. (Примеры здесь).

Apache HTTP Client 4.x(кроме самой ранней версии) имеет прямую поддержку для передачи SSLContext.

Ответ 4

От http://hc.apache.org/httpclient-3.x/sslguide.html:

Protocol.registerProtocol("https", 
new Protocol("https", new MySSLSocketFactory(), 443));
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.whatever.com/");
try {
  httpclient.executeMethod(httpget);
      System.out.println(httpget.getStatusLine());
} finally {
      httpget.releaseConnection();
}

Здесь можно найти пример MySSLSocketFactory здесь. Он ссылается на TrustManager, который вы можете изменить, чтобы доверять всему (хотя вы должны это учитывать!)

Ответ 5

Способ Apache HttpClient 4.5:

org.apache.http.ssl.SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
sslContextBuilder.loadTrustMaterial(new org.apache.http.conn.ssl.TrustSelfSignedStrategy());
SSLContext sslContext = sslContextBuilder.build();
org.apache.http.conn.ssl.SSLConnectionSocketFactory sslSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new org.apache.http.conn.ssl.DefaultHostnameVerifier());

HttpClientBuilder httpClientBuilder = HttpClients.custom().setSSLSocketFactory(sslSocketFactory);
httpClient = httpClientBuilder.build();

ПРИМЕЧАНИЕ: org.apache.http.conn.ssl.SSLContextBuilder устарел, а org.apache.http.ssl.SSLContextBuilder - новый (уведомление conn отсутствует в последнем имени пакета).

Ответ 6

Как только у вас есть Java Cert Store (используя отличный класс InstallCert, созданный выше), вы можете получить java для его использования, передав параметр javax.net.ssl.trustStore при запуске java.

Пример:

java -Djavax.net.ssl.trustStore=/path/to/jssecacerts MyClassName

Ответ 7

Для Apache HttpClient 4.5+ и Java8:

SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial((chain, authType) -> true).build();

SSLConnectionSocketFactory sslConnectionSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new String[]
        {"SSLv2Hello", "SSLv3", "TLSv1","TLSv1.1", "TLSv1.2" }, null,
        NoopHostnameVerifier.INSTANCE);
CloseableHttpClient client = HttpClients.custom()
        .setSSLSocketFactory(sslConnectionSocketFactory)
        .build();

Но если ваш HttpClient использует ConnectionManager для поиска соединения, например. например:

 PoolingHttpClientConnectionManager connectionManager = new 
         PoolingHttpClientConnectionManager();

 CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory) не имеет эффекта, проблема не устранена.

Поскольку HttpClient использует указанный connectionManager для поиска соединения, и указанный connectionManager не зарегистрировал нашу настроенную SSLConnectionSocketFactory. Чтобы решить эту проблему, необходимо зарегистрировать настроенный SSLConnectionSocketFactory в connectionManager. Правильный код должен выглядеть так:

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

CloseableHttpClient client = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();

Ответ 8

Еще одна проблема, с которой вы можете столкнуться с самоподписанными тестовыми сертификатами, такова:

java.io.IOException: неправильное имя хоста HTTPS: должно быть...

Эта ошибка возникает, когда вы пытаетесь получить доступ к URL-адресу HTTPS. Возможно, вы уже установили сертификат сервера в хранилище ключей JRE. Но эта ошибка означает, что имя сертификата сервера не совпадает с фактическим доменным именем сервера, указанным в URL-адресе. Обычно это происходит, когда вы используете сертификат, выданный без CA.

В этом примере показано, как написать HttpsURLConnection DefaultHostnameVerifier, который игнорирует имя сервера сертификатов:

http://www.java-samples.com/showtutorial.php?tutorialid=211

Ответ 9

Для того, чтобы легко добавлять хосты, которым вы доверяете во время выполнения, не выкидывая все проверки, попробуйте код здесь: http://code.google.com/p/self-signed-cert-trust-manager/.

Ответ 10

EasySSLProtocolSocketFactory давал мне проблемы, поэтому я закончил реализацию своего собственного протокола ProtocolSocketFactory.

Сначала вам необходимо его зарегистрировать:

Protocol.registerProtocol("https", new Protocol("https", new TrustAllSSLSocketFactory(), 443));

HttpClient client = new HttpClient();
...

Затем реализуем ProtocolSocketFactory:

class TrustAllSSLSocketFactory implements ProtocolSocketFactory {

    public static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
        new X509TrustManager() {
            public void checkClientTrusted(final X509Certificate[] certs, final String authType) {

            }

            public void checkServerTrusted(final X509Certificate[] certs, final String authType) {

            }

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

    private TrustManager[] getTrustManager() {
        return TRUST_ALL_CERTS;
    }

    public Socket createSocket(final String host, final int port, final InetAddress clientHost,
                               final int clientPort) throws IOException {
        return getSocketFactory().createSocket(host, port, clientHost, clientPort);
    }

    @Override
    public Socket createSocket(final String host, final int port, final InetAddress localAddress,
                               final int localPort, final HttpConnectionParams params) throws IOException {
        return createSocket(host, port);
    }

    public Socket createSocket(final String host, final int port) throws IOException {
        return getSocketFactory().createSocket(host, port);
    }

    private SocketFactory getSocketFactory() throws UnknownHostException {
        TrustManager[] trustAllCerts = getTrustManager();

        try {
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null, trustAllCerts, new SecureRandom());

            final SSLSocketFactory socketFactory = context.getSocketFactory();
            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
            return socketFactory;
        } catch (NoSuchAlgorithmException | KeyManagementException exception) {
            throw new UnknownHostException(exception.getMessage());
        }
    }
}

Примечание. Это с HttpClient 3.1 и Java 8

Ответ 11

Используя InstallCert для создания файла jssecacerts и выполните -Djavax.net.ssl.trustStore=/path/to/jssecacerts работал отлично.

Ответ 12

Этот ссылка объясняет требование, которое вы выполняете шаг за шагом. Если вы действительно не обеспокоены тем, какой сертификат вы можете продолжить, выполните следующую ссылку.

Примечание. Возможно, вам стоит дважды проверить, что вы делаете, это небезопасная операция.

Ответ 13

Я использую httpclient 3.1.X, и это работает для меня

        try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        SslContextSecureProtocolSocketFactory socketFactory = new SslContextSecureProtocolSocketFactory(sslContext,false);
        Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) socketFactory, 443));//同样会影响到HttpUtils
    } catch (Throwable e) {
        e.printStackTrace();

}

public class SslContextSecureProtocolSocketFactory implements      SecureProtocolSocketFactory {

private SSLContext sslContext;
private boolean verifyHostname;

public SslContextSecureProtocolSocketFactory(SSLContext sslContext, boolean verifyHostname) {
    this.verifyHostname = true;
    this.sslContext = sslContext;
    this.verifyHostname = verifyHostname;
}

public SslContextSecureProtocolSocketFactory(SSLContext sslContext) {
    this(sslContext, true);
}

public SslContextSecureProtocolSocketFactory(boolean verifyHostname) {
    this((SSLContext)null, verifyHostname);
}

public SslContextSecureProtocolSocketFactory() {
    this((SSLContext)null, true);
}

public synchronized void setHostnameVerification(boolean verifyHostname) {
    this.verifyHostname = verifyHostname;
}

public synchronized boolean getHostnameVerification() {
    return this.verifyHostname;
}

public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port, clientHost, clientPort);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
    if(params == null) {
        throw new IllegalArgumentException("Parameters may not be null");
    } else {
        int timeout = params.getConnectionTimeout();
        Socket socket = null;
        SSLSocketFactory socketfactory = this.getSslSocketFactory();
        if(timeout == 0) {
            socket = socketfactory.createSocket(host, port, localAddress, localPort);
        } else {
            socket = socketfactory.createSocket();
            InetSocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
            InetSocketAddress remoteaddr = new InetSocketAddress(host, port);
            socket.bind(localaddr);
            socket.connect(remoteaddr, timeout);
        }

        this.verifyHostname((SSLSocket)socket);
        return socket;
    }
}

public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(host, port);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    SSLSocketFactory sf = this.getSslSocketFactory();
    SSLSocket sslSocket = (SSLSocket)sf.createSocket(socket, host, port, autoClose);
    this.verifyHostname(sslSocket);
    return sslSocket;
}

private void verifyHostname(SSLSocket socket) throws SSLPeerUnverifiedException, UnknownHostException {
    synchronized(this) {
        if(!this.verifyHostname) {
            return;
        }
    }

    SSLSession session = socket.getSession();
    String hostname = session.getPeerHost();

    try {
        InetAddress.getByName(hostname);
    } catch (UnknownHostException var10) {
        throw new UnknownHostException("Could not resolve SSL sessions server hostname: " + hostname);
    }

    X509Certificate[] certs = (X509Certificate[])((X509Certificate[])session.getPeerCertificates());
    if(certs != null && certs.length != 0) {
        X500Principal subjectDN = certs[0].getSubjectX500Principal();
        List cns = this.getCNs(subjectDN);
        boolean foundHostName = false;
        Iterator i$ = cns.iterator();
        AntPathMatcher matcher  = new AntPathMatcher();
        while(i$.hasNext()) {
            String cn = (String)i$.next();
            if(matcher.match(cn.toLowerCase(),hostname.toLowerCase())) {
                foundHostName = true;
                break;
            }
        }

        if(!foundHostName) {
            throw new SSLPeerUnverifiedException("HTTPS hostname invalid: expected \'" + hostname + "\', received \'" + cns + "\'");
        }
    } else {
        throw new SSLPeerUnverifiedException("No server certificates found!");
    }
}

private List<String> getCNs(X500Principal subjectDN) {
    ArrayList cns = new ArrayList();
    StringTokenizer st = new StringTokenizer(subjectDN.getName(), ",");

    while(st.hasMoreTokens()) {
        String cnField = st.nextToken();
        if(cnField.startsWith("CN=")) {
            cns.add(cnField.substring(3));
        }
    }

    return cns;
}

protected SSLSocketFactory getSslSocketFactory() {
    SSLSocketFactory sslSocketFactory = null;
    synchronized(this) {
        if(this.sslContext != null) {
            sslSocketFactory = this.sslContext.getSocketFactory();
        }
    }

    if(sslSocketFactory == null) {
        sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    }

    return sslSocketFactory;
}

public synchronized void setSSLContext(SSLContext sslContext) {
    this.sslContext = sslContext;
}

}

Ответ 14

Для HttpClient мы можем сделать это:

SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        String uri = new StringBuilder("url").toString();

        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        };

        HttpClient client = HttpClientBuilder.create().setSSLContext(ctx)
                .setSSLHostnameVerifier(hostnameVerifier).build()

Ответ 15

следуйте инструкциям, приведенным ниже для Java 1.7, чтобы создать сертификат SSL с помощью файла программы InstallCert.java.

https://github.com/escline/InstallCert

вы должны перезапустить кота

Ответ 16

Использовал следующее вместе с DefaultTrustManager, и он работал в httpclient как charm. Благодаря тонну!! @Kevin и любой другой участник

    SSLContext ctx = null;
    SSLConnectionSocketFactory sslsf = null;
    try {

        ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        sslsf = new SSLConnectionSocketFactory(
                ctx,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());

    } catch (Exception e) {
        e.printStackTrace();
    }

     CloseableHttpClient client = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();