忽略 Apache HTTPClient 4.5 中的自签名证书尝试 #1尝试 #2尝试 #3尝试 #4

我正在尝试接受所有证书,和/或使用 Apache HTTPClient 版本 4.5 接受自签名证书(此处为教程链接)

我一直在从SO上的一堆帖子中研究这个问题的解决方案。到目前为止,它们都没有奏效。

我不断收到此错误:尝试执行请求时出错。 javax.net.ssl.SSLHandshake异常:握手期间远程主机关闭连接

Apache Docs:

相关的堆栈溢出问题 - 以下是我尝试过的解决方案的一些链接:

请注意,在所有这些示例中,我还传递了我之前定义的 cookie 存储和代理凭据提供程序。这些是有效的,我只是试图添加SSL支持。

尝试 #1

使用 创建我自己的 ssl 上下文,并使用 信任所有自签名策略。SSLContextBuilderTrustSelfSignedStrategy

SSLContextBuilder sshbuilder = new SSLContextBuilder();
sshbuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sshbuilder.build());

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

结果:不起作用。有Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

尝试 #2

同上,但添加一个PoolingHttpClientConnectionManager

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(2000);//max connection

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .setConnectionManager(cm)
    .build();

结果:不起作用。有Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

尝试 #3

只需通过覆盖(不建议这样做)来接受所有证书TrustStrategy

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

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

结果:不起作用。有Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

尝试 #4

我从这个答案中发现了一些有用的东西:

从版本 4.5 开始,默认情况下,HttpClient 禁用 SSLv3 协议版本

以下是他给出的解决方案:

SSLContext sslcontext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
        sslcontext, new String[] { "TLSv1", "SSLv3" }, null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.INSTANCE)
        .register("https", sslConnectionSocketFactory)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslConnectionSocketFactory)
    .setConnectionManager(cm)
    .build();

结果:不起作用。有Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake


答案 1

我正在使用Apache HttpClient 4.5.3,上述解决方案都没有帮助。我总是得到错误

PKIX Path 构建失败

.

我在 http://www.baeldung.com/httpclient-ssl 中找到了解决方案

这是我的代码:

try {
    SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null, (certificate, authType) -> true).build();
    httpClient = HttpClients.custom().setSSLContext(sslContext)
            .setSSLHostnameVerifier(new NoopHostnameVerifier())
            .build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
    e.printStackTrace();
}

答案 2

通常,您不仅需要支持自签名证书,还需要调用多线程请求,因此使用池化连接管理器。我是这样做的:

private CloseableHttpClient newClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    SSLContext context = SSLContexts.custom()
            .loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE)
            .build();

    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE))
            .build();

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

    return HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();
}