关于Java:如何忽略Apache HttpClient 4.0中的SSL证书错误

How to ignore SSL certificate errors in Apache HttpClient 4.0

如何绕过Apache HttpClient 4.0的无效SSL证书错误?


所有其他答案都已弃用或不适用于HttpClient 4.3。

这是构建http客户端时允许所有主机名的一种方法。

1
2
3
4
CloseableHttpClient httpClient = HttpClients
    .custom()
    .setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE)
    .build();

或者,如果您使用的是版本4.4或更高版本,则更新后的调用如下所示:

1
2
3
4
CloseableHttpClient httpClient = HttpClients
    .custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .build();


您需要使用自己的TrustManager创建SSLContext并使用此上下文创建HTTPS方案。这是代码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);


只需使用较新的HttpClient 4.5来执行此操作,似乎它们从4.4开始就已弃用了一些功能,因此这是适用于我并使用最新API的代码段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.1可以轻松得多

1
2
3
4
5
6
7
8
9
    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

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

    });


Apache HttpClient 4.5.5

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

没有使用过时的API。

简单的可验证测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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;
    }
}


作为记录,已通过httpclient 4.3.6测试并与fluent api的Executor兼容:

1
2
3
4
5
6
7
8
9
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();


对于Apache HttpClient 4.4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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,它们不起作用。我花了数小时来尝试并用尽所有可能的方法,但是似乎在4.4进行了非常重大的API更改和重定位。

另请参见稍微完整的解释:http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

希望有帮助!


如果您要做的是摆脱无效的主机名错误,则可以执行以下操作:

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


我们正在使用HTTPClient 4.3.5,并且我们尝试了几乎所有解决方案都存在于stackoverflow上,但是没有任何解决方案,
在思考并找出问题所在之后,我们来看下面的代码,它们可以很好地工作,
只需在创建HttpClient实例之前添加它即可。

some method to call when making post requests....

1
2
3
4
5
6
7
8
9
10
11
12
13
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);

continue your request in the normal form


使用流利的4.5.2,我必须进行以下修改才能正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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) {
    }


这就是我的做法-

  • 创建我自己的MockSSLSocketFactory(下面附有类)
  • 用它来初始化DefaultHttpClient。如果使用代理,则需要提供代理设置。
  • 初始化DefaultHTTPClient-

    1
    2
    3
    4
    5
    6
    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工厂-

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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;
        }
    };
    }

    如果是代理人,则需要这样做-

    1
    2
    3
    4
    5
    6
    7
    8
    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));


    要接受HttpClient 4.4.x中的所有证书,可以在创建httpClient时使用以下一种衬里:

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


    作为ZZ Coder答案的扩展,最好覆盖hostnameverifier。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // ...
    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 {
        }
    });
    // ...


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
            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);
        }

    使用Fluent API在HttpClient 4.5.5上进行了测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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();

    以下代码适用于4.5.5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    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()));
        }
    }

    代码的输出是

    Code

    浏览器上的输出是

    Bad SSL

    使用的pom在下面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    <?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>
        testing</artifactId>
        <version>1.0-SNAPSHOT</version>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    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>
            httpclient</artifactId>
            <version>4.5.5</version>
        </dependency>

    </dependencies>
    </project>


    Apache HttpClient 4.1.3的完整工作版本(基于上面的oleg代码,但在我的系统上仍需要allow_all_hostname_verifier):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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);
        }
    }

    注意,我将重新抛出所有异常,因为实际上,如果在真实系统中任何失败都将无济于事!


    经过4.3.3测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    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;
    }

    }


    如果使用的是流畅的API,则需要通过Executor进行设置:

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

    ...其中sslContext是创建的SSLContext,如ZZ编码器的答案所示。

    之后,您可以按以下方式执行http请求:

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

    注意:已通过HttpClient 4.2测试


    在4.5.4上测试:

    1
    2
    3
    4
    5
    6
    7
    8
                SSLContext sslContext = new SSLContextBuilder()
                        .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build();

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

    首先,使用JAX-RS 2.x的" RestEasy"实现来构建特殊的"信任所有人"客户端的示例...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
        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;
                }
            };
        }

    相关的Maven依赖项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            resteasy-client</artifactId>
            <version>3.0.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            jaxrs-api</artifactId>
            <version>3.0.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            resteasy-jackson2-provider</artifactId>
            <version>3.0.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            httpclient</artifactId>
            <version>4.5</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

    如果您在使用嵌入Apache HttpClient 4.1的AmazonS3Client时遇到此问题,则只需定义这样的系统属性,即可放宽SSL证书检查器:

    -Dcom.amazonaws.sdk.disableCertChecking = true

    恶作剧管理


    如果您使用的是Apache httpClient 4.5.x,请尝试以下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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();
    }