HttpClient javax.net.ssl.SSLPeerUnverifiedException:时移时对等方未通过身份验证?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24752485/
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
HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated when time shifted?
提问by Liping Huang
Due to the requirement, we need test the https connection by shift the system date to a future date like 2025-05-05, the problem is when using the HttpClient
(version 4.2), will encounter the exception
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
由于需求,我们需要通过将系统日期移到未来日期如2025-05-05来测试https连接,问题是使用HttpClient
(版本4.2)时,会遇到异常
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
The simple code segment as below:
简单的代码段如下:
@Test
public void httpsShouldWorking() throws Exception {
HttpClient client = new DefaultHttpClient();
String urlOverHttps = "https://URL";
HttpGet getMethod = new HttpGet(urlOverHttps);
HttpResponse response = client.execute(getMethod);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
Also I google it and found a solution HttpClient with SSL
我也谷歌它并找到了一个解决方案HttpClient with SSL
as mentioned:
如前所述:
Let's now configure the http client to trust all certificate chains regardless of their validity:
现在让我们将 http 客户端配置为信任所有证书链,而不管它们的有效性:
But after the try, it is not working and still get the auth exception.
但是在尝试之后,它不起作用并且仍然得到身份验证异常。
Is there a solution to avoid the auth when shift the system date?
移动系统日期时是否有避免身份验证的解决方案?
采纳答案by Liping Huang
It is possible to make HttpClient get around the checks of SSL certificate validity. This code can be used to obtain an instance of HttpClient:
可以让 HttpClient 绕过 SSL 证书有效性检查。此代码可用于获取 HttpClient 的实例:
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
......
private static HttpClient getHttpClient() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null,
new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
}}, new SecureRandom());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
return httpClient;
} catch (Exception e) {
e.printStackTrace();
return HttpClientBuilder.create().build();
}
}
The exception will no longer be thrown, when the certification is expired, the browser will issues a warning about an expired certificate and let user confirm.
不再抛出异常,当证书过期时,浏览器会发出证书过期的警告并让用户确认。
回答by sunsys
public static HttpClient verifiedClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("SSL");
X509TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager mgr = base.getConnectionManager();
SchemeRegistry registry = mgr.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
return new DefaultHttpClient(mgr, base.getParams());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
回答by OASE Software GmbH
Instead of disabling the entire Security-Chain it would be much better to import a specific certificate to the keystore of your JAVA installation. How to do this, you can find out here: http://java67.blogspot.co.at/2012/09/keytool-command-examples-java-add-view-certificate-ssl.html
与其禁用整个安全链,不如将特定证书导入 JAVA 安装的密钥库。如何做到这一点,你可以在这里找到:http: //java67.blogspot.co.at/2012/09/keytool-command-examples-java-add-view-certificate-ssl.html
回答by Renann
After reading a lot of asnwers, this was the one that helped me.
在阅读了很多答案后,这是帮助我的一个。
I solved my problem by ignoring some TLS algorithms.
我通过忽略一些 TLS 算法解决了我的问题。
Edit file: $JAVA_HOME/jre/lib/security/java.security
编辑文件: $JAVA_HOME/jre/lib/security/java.security
Add these two algorithms in the list DHE, ECDHE
by appending them to the jdk.tls.disabledAlgorithms
.
通过将这两个算法DHE, ECDHE
附加到jdk.tls.disabledAlgorithms
.
So the end result, in my case, was:
因此,就我而言,最终结果是:
jdk.tls.disabledAlgorithms=SSLv3, DHE, ECDHE
jdk.tls.disabledAlgorithms=SSLv3, DHE, ECDHE
回答by RicardoS
In my case, on the following scenario:
就我而言,在以下情况下:
- JDK8
- Running from a Junit test
- Using resteasy-client
- JDK8
- 从 Junit 测试运行
- 使用resteasy客户端
The following parameter worked:
以下参数有效:
-Djdk.tls.client.protocols=TLSv1
For more information, take a look at:
https://www.java.com/en/configure_crypto.html
有关更多信息,请查看:https:
//www.java.com/en/configure_crypto.html