忽略 Apache HTTPClient 4.5 中的自签名证书 [英] Ignore self-signed certificates in Apache HTTPClient 4.5

查看:33
本文介绍了忽略 Apache HTTPClient 4.5 中的自签名证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to accept all certificates, and/or accept self-signed certificates using Apache HTTPClient version 4.5 (tutorial link here)

我一直在从一堆关于 SO 的帖子中寻找解决这个问题的方法.到目前为止,他们都没有工作.

I've been going through solutions to this problem from a bunch of posts on SO. So far none of them have worked.

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

I keep getting this error: Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Apache 文档:

  • Apache v4.5 tutorial
  • SSL/TLS customization
  • Apache has a guide for version 3, but not version 4.

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

Related StackOverflow Questions - Here's some links of the solutions I've tried:

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

Note that in all these examples I am also passing a cookie store and a proxy credentials provider that I defined earlier. These are working, I'm just trying to add SSL support.

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

Create my own ssl context with SSLContextBuilder and trust all self signed strategies with TrustSelfSignedStrategy.

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

结果:无效.尝试执行请求时遇到 错误.javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接

RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

同上,但添加一个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();

结果:无效.尝试执行请求时遇到 错误.javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接

RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

通过覆盖 TrustStrategy 简单地接受所有证书(不推荐这样做)

Simply accept ALL certificates by overriding the TrustStrategy (this is not recommended)

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

结果:无效.尝试执行请求时遇到 错误.javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接

RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

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

I found something useful from this answer:

从 4.5 版开始,HttpClient 通过以下方式禁用 SSLv3 协议版本默认

As of version 4.5 HttpClient disables SSLv3 protocol version by default

这是他给出的解决方案:

Here's the solution he gave:

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

结果:无效.尝试执行请求时遇到 错误.javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接

RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

推荐答案

上述方法之一应该适用于自签名证书,但奇怪的是您在所有方法中都遇到了相同的异常.

One of the above approaches should work in case of self-signed certificates, but the weird thing is you are getting same exception in all the approaches.

我感觉在 SSL 会话建立或握手协议不被客户端或服务器接受.

I feel during SSL session establishment or handshaking protocol is not being accepted either by client or by server.

这里最好的解决方案是调试应用程序.

The best solution here is to debug the application.

如果是tomcat,在setenv.sh或setenv.bat文件中添加-Djavax.net.debug=all,然后重启服务器.

In case of tomcat, add -Djavax.net.debug=all in setenv.sh or setenv.bat files and then restart the server.

或者您可以按照本教程.

OP 只需要在连接到 SSL 时更改端口:

The OP just needed to change the port when connecting to SSL:

//For HTTPS
HttpHost httpstarget = new HttpHost("mysite.com", 443, "https");

//For HTTP
HttpHost httptarget = new HttpHost("mysite.com", 80, "http");

这篇关于忽略 Apache HTTPClient 4.5 中的自签名证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆