Apache httpclient javax.net.ssl.SSLHandshakeException:
Posted
技术标签:
【中文标题】Apache httpclient javax.net.ssl.SSLHandshakeException:【英文标题】:Apache httpclient javax.net.ssl.SSLHandshakeException: 【发布时间】:2014-04-10 16:14:22 【问题描述】:我正在尝试连接到具有 SSLv3 安全性的服务。
提供以下文件后,curl和浏览器就可以通信了
1. ca.crt
2. private.key
2. client.crt
我使用所有 3 个文件创建了一个带有以下 cmd 的 ssl 密钥库
openssl pkcs12 -export -in client.crt -inkey private.key -CAfile ca.crt -out sslstore.p12
然后使用keytool将其导入为java truststore
keytool -importkeystore -srckeystore sslstore.p12 -srcstoretype PKCS12 -destkeystore truststore.jks
之后,我点击了以下链接https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java 连接到网址。仅将协议从 TLSv1 更改为 SSLv3。
我总是在连接时得到 javax.net.ssl.SSLHandshakeException: excdption。
如前所述,这些键适用于 curl / 浏览器。
EDIT-2 更改 SSLContexts.custom() 附近的代码
来自:
sslcontext = SSLContexts.custom()
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.build();
到:
sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "changeit".toCharArray())
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.build();
工作。请注意,我使用的是相同的密钥库。
EDIT-1 代码:
public static void main (String[] args) throws KeyStoreException, FileNotFoundException
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("certs/ppro.jks");
try
keyStore.load(is,"changeit".toCharArray());
catch (IOException | NoSuchAlgorithmException | CertificateException e)
e.printStackTrace();
// Trust own CA and all self-signed certs
SSLContext sslcontext = null;
try
sslcontext = SSLContexts.custom()
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.build();
catch (NoSuchAlgorithmException | KeyManagementException e)
e.printStackTrace();
try
sslcontext.loadKeyMaterial(keyStore,"changeit".toCharArray());
catch (NoSuchAlgorithmException | KeyManagementException e)
e.printStackTrace();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] "SSLv3" ,
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
try (CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build())
HttpPost httpPost = new HttpPost(URL);
try
CloseableHttpResponse response = httpclient.execute(httpPost);
System.out.println(response);
catch (IOException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
EDIT-0
这是来自 java 的堆栈跟踪,包括一些 ssl 调试信息。
*** ClientKeyExchange, RSA PreMasterSecret, SSLv3
main, WRITE: SSLv3 Handshake, length = 132
SESSION KEYGEN:
PreMaster Secret:
0000: 03 00 E7 89 C2 9D AB 1A 3B 75 85 5B 4E C6 EE 10 ........;u.[N...
0010: 83 0F 3C 37 74 3C D0 6A AF 51 D7 EC E2 B9 50 35 ..<7t<.j.Q....P5
0020: CC 8D 58 93 39 5D B6 4F BE DB 5A F4 E3 0A BE 42 ..X.9].O..Z....B
CONNECTION KEYGEN:
Client Nonce:
0000: 53 47 9A BD 4B 14 BC AF B0 2B FB 6C 49 9C E4 53 SG..K....+.lI..S
0010: 21 F3 53 C8 7F 74 1C 5C C0 5E 6D 67 18 50 10 4D !.S..t.\.^mg.P.M
Server Nonce:
0000: 53 47 9A BD B2 5C 44 89 92 BE 4B FF F4 F6 60 FE SG...\D...K...`.
0010: D6 18 67 96 6A 13 3C 80 9F D2 56 29 1A 60 B4 E4 ..g.j.<...V).`..
Master Secret:
0000: E3 E5 11 9F 87 B6 A3 4E 8C 9C F1 20 E9 A5 50 62 .......N... ..Pb
0010: DD E8 E6 A3 61 FC C0 56 0C 1E A8 29 BC F4 5C 52 ....a..V...)..\R
0020: DE CE 98 64 0E 57 07 E6 22 24 08 1A 77 8A 97 48 ...d.W.."$..w..H
Client MAC write Secret:
0000: 44 98 8B 9C C4 59 C2 4E 21 66 67 6D 96 C4 FE 9C D....Y.N!fgm....
0010: 2B 74 AD 61 +t.a
Server MAC write Secret:
0000: 29 7D 5A F2 71 B6 55 C0 CF BB 82 66 02 03 B1 35 ).Z.q.U....f...5
0010: 5A 69 83 99 Zi..
Client write key:
0000: B5 32 F7 7C DC DB 4F B4 00 48 66 A4 B3 C0 7D 6B .2....O..Hf....k
Server write key:
0000: CB 80 F4 76 53 92 6F 87 3B A3 9D B2 A9 6F 40 85 ...vS.o.;....o@.
Client write IV:
0000: B7 89 4A FC 43 7A 1B 3C DD 83 7F CE A1 FC FB BF ..J.Cz.<........
Server write IV:
0000: 84 92 B7 B4 EB 13 B6 77 EF 87 B0 E1 04 41 5C 4D .......w.....A\M
main, WRITE: SSLv3 Change Cipher Spec, length = 1
*** Finished
verify_data: 116, 66, 54, 146, 216, 200, 254, 221, 170, 236, 204, 2, 17, 139, 161, 37, 205, 117, 131, 95, 255, 123, 158, 100, 150, 110, 105, 209, 22, 205, 31, 196, 95, 84, 59, 252
***
main, WRITE: SSLv3 Handshake, length = 64
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
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 org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at com.masterpayment.frontend.gateway.beconnector.GiroGateClient.main(GiroGateClient.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
main, READ: SSLv3 Alert, length = 2
main, RECV SSLv3 ALERT: fatal, handshake_failure
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
【问题讨论】:
【参考方案1】:apache 示例只设置了一个信任库。那只会使用 CA 证书。您还需要设置一个“身份”来处理客户端证书。我知道您将它们全部放在同一个 java 密钥库中,这可能仍然可以(但通常它们位于单独的文件中)。
该示例调用 loadTrustMaterial()。您还需要调用 loadKeyMaterial()。
【讨论】:
你能提供一个例子或一个链接吗?如何创建身份? 您似乎已经创建了一个身份。您只是碰巧将它与 CA 证书放在同一个密钥库中。请在 SSLContexts.custom() 周围发布您的代码 我将 SSLContexts.custom() 周围的代码更改为 sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore, "changeit".toCharArray()) .loadTrustMaterial(keyStore, new TrustSelfSignedStrategy()) 。构建();【参考方案2】:我的直觉是您遇到了 PKIX 链验证错误 - 请尝试以下操作:
openssl pkcs12 \
-export \
-chain \
-in client.crt \
-inkey private.key \
-CAfile ca.crt \
-out sslstore.p12
请注意以上内容 - 我添加了“-chain”选项 - 这应该使用适当的证书链接将证书正确导出到 PKCS#12 存档中。
在过去的 6 个月里,我遇到这种情况的次数超过了我的数,而且它总是让我着迷。
如果这不起作用,请同时添加一些来自 Java 的堆栈跟踪。
【讨论】:
我试过了。这次我得到了 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: error。我已经将 ca.crt 导入 $JRE_HOME/lib/security/cacerts 在我将 ca.crt 导入信任库之前会发生这种情况。导入后,我得到了原始问题中提到的异常。 呃,我讨厌那个例外的含糊不清。我想尝试在本地证明这一点,你能告诉我你使用的是哪个版本 我使用的是 apche httpclient 的 4.3.3以上是关于Apache httpclient javax.net.ssl.SSLHandshakeException:的主要内容,如果未能解决你的问题,请参考以下文章
commons-httpclient 和 httpclient 之间有啥关系,都来自 apache
新旧apache HttpClient 获取httpClient方法
Apache HttpClient API 中的 CloseableHttpClient 和 HttpClient 有啥区别?