java 忽略 Apache HTTPClient 4.5 中的自签名证书
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39922714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ignore self-signed certificates in Apache HTTPClient 4.5
提问by Katie
I am trying to accept all certificates, and/or accept self-signed certificatesusing Apache HTTPClient version 4.5(tutorial link here)
我正在尝试接受所有证书,和/或接受使用Apache HTTPClient 4.5 版的自签名证书(此处的教程链接)
I've been going through solutions to this problem from a bunch of posts on SO. So far none of them have worked.
我一直在从一堆关于 SO 的帖子中解决这个问题。到目前为止,他们都没有工作。
I keep getting this error: Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
我不断收到此错误: Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Apache Docs:
阿帕奇文档:
- Apache v4.5 tutorial
- SSL/TLS customization
- Apache has a guidefor version 3, but not version 4.
- Apache v4.5 教程
- SSL/TLS 定制
- Apache 有版本 3的指南,但没有版本 4。
Related StackOverflow Questions- Here's some links of the solutions I've tried:
相关的 StackOverflow 问题- 以下是我尝试过的解决方案的一些链接:
- Ignoring SSL certificate in Apache HttpClient 4.3
- How to ignore SSL certificate errors in Apache HttpClient 4.0
- Ignore SSL Certificate Errors with Java
- Need to trust all the certificates during the development using Spring
- How to handle invalid SSL certificates with Apache HttpClient?
- 忽略 Apache HttpClient 4.3 中的 SSL 证书
- 如何忽略 Apache HttpClient 4.0 中的 SSL 证书错误
- 使用 Java 忽略 SSL 证书错误
- 在使用 Spring 的开发过程中需要信任所有证书
- 如何使用 Apache HttpClient 处理无效的 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.
请注意,在所有这些示例中,我还传递了我之前定义的 cookie 存储和代理凭据提供程序。这些工作正常,我只是想添加 SSL 支持。
Try #1
尝试 #1
Create my own ssl context with SSLContextBuilder
and trust all self signed strategies with TrustSelfSignedStrategy
.
创建我自己的 ssl 上下文SSLContextBuilder
并信任所有自签名策略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();
RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
结果:没用。拿到Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Try #2
尝试 #2
Same as above, but add a PoolingHttpClientConnectionManager
与上面相同,但添加一个 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();
RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
结果:没用。拿到Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Try #3
尝试 #3
Simply accept ALL certificates by overriding the TrustStrategy
(this is not recommended)
只需通过覆盖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();
RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
结果:没用。拿到Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Try #4
尝试 #4
I found something useful from this answer:
我从这个答案中发现了一些有用的东西:
As of version 4.5 HttpClient disables SSLv3 protocol version by default
从 4.5 版开始,HttpClient 默认禁用 SSLv3 协议版本
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();
RESULT: Didn't work. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
结果:没用。拿到Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
采纳答案by Azim
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.
上述方法之一应该适用于自签名证书,但奇怪的是您在所有方法中都遇到了相同的异常。
I feel during SSL session establishment or handshaking protocol is not being accepted either by client or by server.
我觉得在 SSL 会话建立期间或握手协议不被客户端或服务器接受。
The best solution here is to debug the application.
这里最好的解决方案是调试应用程序。
In case of tomcat, add -Djavax.net.debug=allin setenv.sh or setenv.bat files and then restart the server.
如果是tomcat,在setenv.sh或setenv.bat文件中添加-Djavax.net.debug=all,然后重启服务器。
Or you can follow this tutorial.
或者您可以按照本教程进行操作。
The OP just needed to change the port when connecting to SSL:
OP 只需要在连接到 SSL 时更改端口:
//For HTTPS
HttpHost httpstarget = new HttpHost("mysite.com", 443, "https");
//For HTTP
HttpHost httptarget = new HttpHost("mysite.com", 80, "http");
回答by Martin Pabst
I'm using Apache HttpClient 4.5.3 and none of the above solutions helped. I always got the error
我正在使用 Apache HttpClient 4.5.3,但上述解决方案都没有帮助。我总是收到错误
PKIX Path building failed
PKIX 路径构建失败
.
.
I found the solution in http://www.baeldung.com/httpclient-ssl
我在http://www.baeldung.com/httpclient-ssl找到了解决方案
Here's my code:
这是我的代码:
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();
}
回答by Yaniv Nahoum
Very often you not only need to support self signed certificates, but also invoke multi-threaded requests, and so use a pooling connection manager. Here's how I do it:
很多时候,您不仅需要支持自签名证书,还需要调用多线程请求,因此使用池连接管理器。这是我的方法:
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();
}
回答by Oleg Maksymuk
This problem is about SSL connection. When you try to connect to some resource https protocolrequires to create secured connection. That means only your browser and website server know what data is being sent in requests bodies. This security is achieved by ssl certificates that stored on website and are being downloaded by your browser (or any other client, Apache Http Client in our case) with first connection to host. There are RSA256 encryption and many other cool things around. But in the end of a day: In case certificate is not registered or is invalid you will see certificate error (HTTPS connection is not secure). To fix certificate error website provider need to buy it for particular website or fix somehow e.g. https://www.register.com/ssl-certificates
这个问题是关于 SSL 连接的。当您尝试连接到某些资源时,https 协议需要创建安全连接。这意味着只有您的浏览器和网站服务器知道在请求正文中发送了哪些数据。这种安全性是通过存储在网站上的 ssl 证书实现的,并且正在由您的浏览器(或任何其他客户端,在我们的案例中为 Apache Http 客户端)通过第一次连接到主机来实现。周围有 RSA256 加密和许多其他很酷的东西。但归根结底:如果证书未注册或无效,您将看到证书错误(HTTPS 连接不安全)。要修复证书错误网站提供商需要为特定网站购买或以某种方式修复例如https://www.register.com/ssl-certificates
however there is an bypass when you skip ssl verification with
但是当你跳过 ssl 验证时有一个绕过
(s, sslSession) -> true
that is security violation because you are not 100% sure that your data is secured, however this solution can used for testing or configuration when use test data and trusted websites
这是安全违规,因为您不能 100% 确定您的数据是安全的,但是当使用测试数据和受信任的网站时,此解决方案可用于测试或配置
public static HttpClient newClient() {
SSLContext sslcontext = null;
try {
sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext,
(s, sslSession) -> true);
return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
.build();
}