Як ігнорувати помилки сертифікатів SSL в Apache HttpClient 4.0


125

Як я обходжу недійсні помилки сертифіката SSL за допомогою Apache HttpClient 4.0?


12
Слід зазначити, що відповіді на це питання не виконують більше того, що задають: вони дозволяють вам ігнорувати помилку, але не виправляти основну проблему (трохи схоже на вилучення акумуляторів з димового сигналу, а не гасіння пожежі ). Сертифікати мають на меті забезпечити безпеку з'єднання SSL / TLS, ігнорування цих помилок вводить вразливість до атаки MITM. Використовуйте тестові сертифікати замість ігнорування помилки.
Бруно


46
"як видалення батарей від димового сигналу" Ви можете поставити перед іншими розробниками користь від сумнівів і припустити, що вони знають, що роблять. Можливо, мотивацією цього питання є локальне тестування, і ОП бажає провести швидкий тест, не проходячи жахливих кількостей платформи Java, необхідних для створення навіть простого середовища SSL. Можливо, хтось міг би просто відповісти на питання, не переходячи на лекцію "холіє, ніж ти".
Майк

Тобто, у внутрішнього сервера JIRA в нашій компанії є деякий "cert на основі політики безпеки Windows", який дійсний на машинах Windows, включених у домен, а не на інших. Я не можу контролювати цю політику і все ще хочу зателефонувати JIRA REST API.
odiszapc

1
@Bruno Неможливість відключити сповіщувачі диму протягом 30-60 хвилин під час роботи з невеликим кухонним вогнем свідчить про шалену відсутність розуміння моделей використання деяким юридичним чиновником у якийсь момент, що я відчуваю межу з кримінальним. Факт «вилучення акумуляторів з димової сигналізації» підтверджує це. Я відчуваю приблизно однаковий рівень гніву з приводу того, що мені потрібно отримати сертифікати для роботи на простий тест, який, наскільки я знаю, не має наслідків для безпеки. Існування цього питання це доводить.
Білл К

Відповіді:


84

Вам потрібно створити SSLContext з власним TrustManager та створити схему HTTPS, використовуючи цей контекст. Ось код,

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

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

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

// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);

1
Скажіть, я не хочу купувати дійсний сертифікат SSL для свого сайту, а просто хочу його використовувати, цей фрагмент коду може допомогти? Чому я не бачу жодної частини, де потрібна URL-адреса або потрібна обробка виключень?
В'єт

19
Гм, це мені говорить, що "новий SSLSocketFactory (ssslCont)" очікує KeyStore, а не SSLContext. Я щось пропускаю?
MSpeed

2
Я отримую помилку, що X509TrustManager не може бути переданий TrustManager.
МВт.

2
Переконайтеся, що ви імпортуєте правильні пакети, тобто з org.apache.http.
начальник

2
Хтось знає, як все це зробити разом, використовуючи HttpClientBuilder?
Алі

112

Усі інші відповіді або застаріли, або не працювали для HttpClient 4.3.

Ось спосіб дозволити всі імена хостів під час створення http-клієнта.

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE)
    .build();

Або якщо ви використовуєте версію 4.4 або новішу, оновлений виклик виглядає приблизно так:

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .build();

Дякую за відповідь, я хотів би знати, з якого пакету є HttpsClients, як я використовую в компіляції Android ("org.apache.httpcomponents: httpclient: 4.3.4"), але цей клас не з'являється.
Хуан Саравія

1
Це пакет org.apache.http.impl.client.HttpClients.
erversteeg

14
Це працює проти невідповідності імені хоста (я припускаю), але, схоже, це не працює, коли сертифікат не підписується довіреною владою.
twm

1
@twm, тому він говорить, що "дозволяє всі імена хостів", для довіри потрібні різні конфігурації.
eis

1
@eis, я вказував, що ця відповідь стосується оригінального питання в певних випадках, але не в інших.
twm

43

Просто довелося це зробити з новим HttpClient 4.5, і здається, що вони застаріли декілька речей з 4.4, ось ось фрагмент, який працює для мене і використовує останній API:

final SSLContext sslContext = new SSLContextBuilder()
        .loadTrustMaterial(null, (x509CertChain, authType) -> true)
        .build();

return HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .setConnectionManager(
                new PoolingHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.INSTANCE)
                                .register("https", new SSLConnectionSocketFactory(sslContext,
                                        NoopHostnameVerifier.INSTANCE))
                                .build()
                ))
        .build();

Працював для мене також для httpclient 4.5.2
Вікас Ранджан

ця версія є актуальною для HttpClient 4.5
Ви приголомшливі

31

Тільки для запису існує набагато простіший спосіб досягти того ж з HttpClient 4.1

    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

        public boolean isTrusted(
                final X509Certificate[] chain, String authType) throws CertificateException {
            // Oh, I am easy...
            return true;
        }

    });

1
Ви пропускаєте якийсь код у цьому зразку? Можливо, дзвінок на httpClient.set ...?
Сірий

6
httpclient.getConnectionManager (). getSchemeRegistry (). register (нова схема ("https", 443, sslsf));
Бен Флінн

8
SSLSocketFactory застаріло в HttpClient 4.3
Toilal

1
Якщо ви використовуєте Java 8, ви навіть можетеnew SSLSocketFactory((chain, authType) -> true);
jlb

28

Apache HttpClient 4.5.5

HttpClient httpClient = HttpClients
            .custom()
            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
            .build();

Жодний застарілий API не використовувався.

Простий тестовий випробувальний випадок:

package org.apache.http.client.test;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class ApacheHttpClientTest {

    private HttpClient httpClient;

    @Before
    public void initClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        httpClient = HttpClients
                .custom()
                .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }

    @Test
    public void apacheHttpClient455Test() throws IOException {
        executeRequestAndVerifyStatusIsOk("https://expired.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://wrong.host.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://self-signed.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://untrusted-root.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://revoked.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://pinning-test.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://sha1-intermediate.badssl.com");
    }

    private void executeRequestAndVerifyStatusIsOk(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        assert statusCode == 200;
    }
}

Дякую! Просто змініть TrustAllStrategy.INSTANCEз TrustSelfSignedStrategy.INSTANCEтакою відповіддю.
Персі Вега

Це для мене не вийшло. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: Не вдалося побудувати шлях PKIX: sun.security. provider.certpath.SunCertPathBuilderException: не вдалося знайти дійсний шлях сертифікації до потрібної цілі
ggb667

26

Для запису, протестованого на httpclient 4.3.6 та сумісного з Виконавцем плавних api:

CloseableHttpClient httpClient = HttpClients.custom().
                    setHostnameVerifier(new AllowAllHostnameVerifier()).
                    setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
                    {
                        public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
                        {
                            return true;
                        }
                    }).build()).build();

3
Для HttpClient 4.4 вгору ви повинні зробити це - і, можливо, також знадобиться створити це, SSLConnectionSocketFactoryвикористовуючи це SSLContext, і визначити це в Registry<ConnectionSocketFactory>, якщо ви збираєтеся створити PoolingHttpClientConnectionManager. Інші відповіді популярніші, але вони не працюють у HttpClient 4.4.
Thomas W

1
Працює саме так із httpclient-4.3.5.jar.
Харальд

18

Для Apache HttpClient 4.4:

HttpClientBuilder b = HttpClientBuilder.create();

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        return true;
    }
}).build();
b.setSslcontext( sslContext);

// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", sslSocketFactory)
        .build();

// allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);

HttpClient client = b.build();

Це витягується з нашої реальної роботи.

Інші відповіді популярні, але для HttpClient 4.4 вони не працюють. Я витратив години на пробування та вичерпання можливостей, але, схоже, було надзвичайно велике зміна API та переїзд у 4.4.

Дивіться також трохи більш повне пояснення на веб-сайті: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Сподіваюся, що це допомагає!


2
Я був тим бітком SSLContext, який мені потрібен. Так сильно зобов’язаний.
БаранинаУп

14

Якщо все, що ви хочете зробити, це позбутися недійсних помилок імені хоста, ви можете просто зробити:

HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
    .getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());

8
Метод sf.setHostnameVerifier застарілий станом на 4.1. Альтернативою є використання одного з конструкторів. Наприклад:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

Це було дуже корисно, коли мені довелося мати справу зі спадковим кодом.
DuncanSungWKim

9

Ми використовуємо HTTPClient 4.3.5, і ми намагалися майже всі рішення існувати на потоці stackoverflow, але нічого, обміркувавши і з'ясувавши проблему, ми переходимо до наступного коду, який ідеально працює, просто додамо його до створення екземпляра HttpClient.

якийсь метод дзвінка під час надсилання запитів ....

SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            return true;
        }
    });

    SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
    HttpPost postRequest = new HttpPost(url);

продовжуйте запит у звичайній формі


7

З вільним вмістом 4.5.2 мені довелося зробити наступну модифікацію, щоб вона працювала.

try {
    TrustManager[] trustAllCerts = new TrustManager[] {
       new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
    public void checkClientTrusted(X509Certificate[] certs, String authType) {  }

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

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSslcontext(sc).build();

    String output = Executor.newInstance(httpClient).execute(Request.Get("https://127.0.0.1:3000/something")
                                      .connectTimeout(1000)
                                      .socketTimeout(1000)).returnContent().asString();
    } catch (Exception e) {
    }

1
Це єдине рішення, яке працювало на мене. Я перепробував вищевикладені рішення для 4.3 і 4.4, перш ніж оновити до 4.5 і спробувати це.
dirkoneill

6

Ось як я це зробив -

  1. Створіть власну MockSSLSocketFactory (Клас додається нижче)
  2. Використовуйте його для ініціалізації DefaultHttpClient. Якщо використовувати проксі, потрібно встановити настройки проксі.

Ініціалізація за замовчуваннямHTTPClient -

SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme("https", 443, new MockSSLSocketFactory()));
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);

    DefaultHttpClient httpclient = new DefaultHttpClient(cm);

Макет SSL Factory -

public class MockSSLSocketFactory extends SSLSocketFactory {

public MockSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(trustStrategy, hostnameVerifier);
}

private static final X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {
    @Override
    public void verify(String host, SSLSocket ssl) throws IOException {
        // Do nothing
    }

    @Override
    public void verify(String host, X509Certificate cert) throws SSLException {
        //Do nothing
    }

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
        //Do nothing
    }

    @Override
    public boolean verify(String s, SSLSession sslSession) {
        return true; 
    }
};

private static final TrustStrategy trustStrategy = new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
};
}

Якщо за проксі-сервером потрібно зробити це -

HttpParams params = new BasicHttpParams();
    params.setParameter(AuthPNames.PROXY_AUTH_PREF, getClientAuthPrefs());

DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);

httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(proxyHost, proxyPort),
                        new UsernamePasswordCredentials(proxyUser, proxyPass));

Це допоможе, якщо ви включите імпорт у майбутньому. Є два різні класи.
AndroidDev

4

На додаток до відповіді ZZ Coder буде непогано переосмислити ідентифікатор хоста.

// ...
SSLSocketFactory sf = new SSLSocketFactory (sslContext);
sf.setHostnameVerifier(new X509HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }

    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
    }

    public void verify(String host, X509Certificate cert) throws SSLException {
    }

    public void verify(String host, SSLSocket ssl) throws IOException {
    }
});
// ...

Цього можна досягти, просто зробивши цеsf.setHostnameVerifier(new AllowAllHostnameVerifier());
Дан Дайер

7
Sf.setHostnameVerifier застарілий станом на 4.1. Альтернативою є використання одного з конструкторів. Наприклад:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

4
        DefaultHttpClient httpclient = new DefaultHttpClient();

    SSLContext sslContext;
    try {
        sslContext = SSLContext.getInstance("SSL");

        // set up a TrustManager that trusts everything
        try {
            sslContext.init(null,
                    new TrustManager[] { new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            log.debug("getAcceptedIssuers =============");
                            return null;
                        }

                        public void checkClientTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkClientTrusted =============");
                        }

                        public void checkServerTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkServerTrusted =============");
                        }
                    } }, new SecureRandom());
        } catch (KeyManagementException e) {
        }
         SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
         ClientConnectionManager ccm = this.httpclient.getConnectionManager();
         SchemeRegistry sr = ccm.getSchemeRegistry();
         sr.register(new Scheme("https", 443, ssf));            
    } catch (Exception e) {
        log.error(e.getMessage(),e);
    }

4

Щоб прийняти всі сертифікати в HttpClient 4.4.x, ви можете використовувати наступний один вкладиш, створюючи httpClient:

httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build()).build();

Я отримую це: Викликано: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Немає альтернативних імен предмета?

Як дозволити підключення до сайтів SSL без сертифікатів в API HttpClient або в API RestClient?

4

Тестували на HttpClient 4.5.5 з Fluent API

final SSLContext sslContext = new SSLContextBuilder()
    .loadTrustMaterial(null, (x509CertChain, authType) -> true).build();

CloseableHttpClient httpClient = HttpClients.custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .setSSLContext(sslContext).build();

String result = Executor.newInstance(httpClient)
    .execute(Request.Get("https://localhost:8080/someapi")
    .connectTimeout(1000).socketTimeout(1000))
    .returnContent().asString();

3

Нижче код працює з 4.5.5

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

class HttpsSSLClient {


    public static CloseableHttpClient createSSLInsecureClient() {
        SSLContext sslcontext = createSSLContext();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new HostnameVerifier() {

            @Override
            public boolean verify(String paramString, SSLSession paramSSLSession) {
                return true;
            }
        });
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        return httpclient;
    }


    private static SSLContext createSSLContext() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[] {new TrustAnyTrustManager()}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslcontext;
    }


    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

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

}
public class TestMe {


    public static void main(String[] args) throws IOException {
        CloseableHttpClient client = HttpsSSLClient.createSSLInsecureClient();

        CloseableHttpResponse res = client.execute(new HttpGet("https://wrong.host.badssl.com/"));
        System.out.println(EntityUtils.toString(res.getEntity()));
    }
}

Вихід з коду є

Код

Вихід у браузері є

Поганий SSL

Пом, що використовується нижче

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tarun</groupId>
    <artifactId>testing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

</dependencies>
</project>

дякую за оновлену відповідь, я нагородив нагороду нового хлопця за "привітання", але я просто хотів оновлених відповідей для всіх!

1
@feelingunwelcome, звичайно. Я також підтримав його :-)
Тарун Лалвані

2

повна робоча версія для Apache HttpClient 4.1.3 (заснована на коді Олега вище, але він все ще потребував у моїй системі дозволу_визначення_визначення):

private static HttpClient trustEveryoneSslHttpClient() {
    try {
        SchemeRegistry registry = new SchemeRegistry();

        SSLSocketFactory socketFactory = new SSLSocketFactory(new TrustStrategy() {

            public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
                // Oh, I am easy...
                return true;
            }

        }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        registry.register(new Scheme("https", 443, socketFactory));
        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
        DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
        return client;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

Зауважте, що я повторно кидаю всі винятки, тому що насправді, я не можу зробити, якщо що-небудь з цього вийде з ладу в реальній системі!


2

Якщо ви використовуєте вільний API , вам потрібно встановити його за допомогою Executor:

Executor.unregisterScheme("https");
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext,
                                  SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Executor.registerScheme(new Scheme("https", 443, sslSocketFactory));

... де sslContextстворений SSLContext, як показано у відповіді ZZ-кодера .

Після цього ви можете виконувати свої запити на http:

String responseAsString = Request.Get("https://192.168.1.0/whatever.json")
                         .execute().getContent().asString();

Примітка: протестовано з HttpClient 4.2


На жаль, застаріле в 4.3: "Застарене. (4.3) не використовувати."
STM

2

Перевірено з 4.3.3

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class AccessProtectedResource {

public static void main(String[] args) throws Exception {

    // Trust all certs
    SSLContext sslcontext = buildSSLContext();

    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://yoururl");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            for (Header header : response.getAllHeaders()) {
                System.out.println(header);
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

private static SSLContext buildSSLContext()
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException {
    SSLContext sslcontext = SSLContexts.custom()
            .setSecureRandom(new SecureRandom())
            .loadTrustMaterial(null, new TrustStrategy() {

                public boolean isTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    return true;
                }
            })
            .build();
    return sslcontext;
}

}


Як встановити значення в заголовках, якщо я хотів це зробити?

2

Тестовано на 4.5.4:

            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build();

            CloseableHttpClient httpClient = HttpClients
                    .custom()
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setSSLContext(sslContext)
                    .build();

0

Якщо ви зіткнулися з цією проблемою під час використання AmazonS3Client, який вбудовує Apache HttpClient 4.1, вам просто потрібно визначити системне властивість на зразок цього, щоб перевірити сертифікат Cert SSL:

-Dcom.amazonaws.sdk.disableCertChecking = вірно

Пустощі вдалося


0

fwiw, приклад використання "RestEasy" реалізації JAX-RS 2.x для створення спеціального клієнта "довіряти всім" ...

    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.security.GeneralSecurityException;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.Arrays;
    import javax.ejb.Stateless;
    import javax.net.ssl.SSLContext;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.HttpClientConnectionManager;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.jboss.resteasy.client.jaxrs.ResteasyClient;
    import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
    import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
    import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
    import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.ssl.SSLContexts;

    @Stateless
    @Path("/postservice")
    public class PostService {

        private static final Logger LOG = LogManager.getLogger("PostService");

        public PostService() {
        }

        @GET
        @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
        public PostRespDTO get() throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException, IOException, GeneralSecurityException {

            //...object passed to the POST method...
            PostDTO requestObject = new PostDTO();
            requestObject.setEntryAList(new ArrayList<>(Arrays.asList("ITEM0000A", "ITEM0000B", "ITEM0000C")));
            requestObject.setEntryBList(new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));

            //...build special "trust all" client to call POST method...
            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(createTrustAllClient());

            ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
            ResteasyWebTarget target = client.target("https://localhost:7002/postRespWS").path("postrespservice");
            Response response = target.request().accept(MediaType.APPLICATION_JSON).post(Entity.entity(requestObject, MediaType.APPLICATION_JSON));

            //...object returned from the POST method...
            PostRespDTO responseObject = response.readEntity(PostRespDTO.class);

            response.close();

            return responseObject;
        }


        //...get special "trust all" client...
        private static CloseableHttpClient createTrustAllClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, TRUSTALLCERTS).useProtocol("TLS").build();
            HttpClientBuilder builder = HttpClientBuilder.create();
            NoopHostnameVerifier noop = new NoopHostnameVerifier();
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, noop);
            builder.setSSLSocketFactory(sslConnectionSocketFactory);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
            HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
            builder.setConnectionManager(ccm);

            return builder.build();
        }


        private static final TrustStrategy TRUSTALLCERTS = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
                return true;
            }
        };
    }

пов'язані залежності Мейвена

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>jaxrs-api</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency> 

-1

Якщо ви використовуєте Apache httpClient 4.5.x, спробуйте це:

public static void main(String... args)  {

    try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
        HttpGet httpget = new HttpGet("https://example.com");
        System.out.println("Executing request " + httpget.getRequestLine());

        httpclient.execute(httpget);
        System.out.println("----------------------------------------");
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

    // use the TrustSelfSignedStrategy to allow Self Signed Certificates
    SSLContext sslContext = SSLContextBuilder
            .create()
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    // we can optionally disable hostname verification. 
    // if you don't want to further weaken the security, you don't have to include this.
    HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

    // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
    // and allow all hosts verifier.
    SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

    // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
    return HttpClients
            .custom()
            .setSSLSocketFactory(connectionFactory)
            .build();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.