https 和 证书认证
错误:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at com.labcorp.efone.vendor.TestATTConnectivity.main(TestATTConnectivity.java:43)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
... 8 more
这个问题涉及到了 SSL/TLS 的握手和通信过程中,安全认证被分为单向认证和双向认证。双向认证就是说,server也会要求验证client的证书,而用Java程序模拟时没有启用证书,所以导致认证阶段出错,握手失败。
解决方法
1、访问https网站,下载证书
a. 浏览器地址栏旁边会有一个锁的图标,点击那个锁,会有查看证书的按钮;
b. 将证书信息导出,证书格式有很多种,der、cer等,我保存的是cer格式的
2、利用jdk的key tool工具,将证书转换成密钥的形式
keytool -import -alias "my alipay cert" -file steven.cert -keystore my.store,keytool -import -alias "my alipay cert" -file steven.cert -keystore my.store
3、sslContext中载入信用证书
private static SSLContext sslcontext;
try {
sslcontext = SSLContexts.custom()
.loadTrustMaterial(new File("D:\\my.keystore"), "123456".toCharArray(),
new TrustSelfSignedStrategy())
.build();
} catch (Exception e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.setDefaultCookieStore(cookieStore)
// 异常重试机制 3次 (网络层面上的)
.setRetryHandler(new DefaultHttpRequestRetryHandler(3,true))
.setDefaultRequestConfig(defaultRequestConfig)
.build();