我正在尝试从Java 9测试新的HttpClient。出于测试目的,我使用的是https://jsonplaceholder.typicode.com提供的api。但是,我收到握手异常,不知道原因。
我正在运行的代码:
private final String TEST_URI = "https://jsonplaceholder.typicode.com/posts";
@Test
public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(TEST_URI))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
}
我收到一个例外:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
at java.base/sun.security.ssl.Alerts.getSSLException(Alerts.java:159)
at java.base/sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1905)
at java.base/sun.security.ssl.SSLEngineImpl.processInputRecord(SSLEngineImpl.java:1140)
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1020)
at java.base/sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:902)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:680)
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:626)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLDelegate.unwrapBuffer(AsyncSSLDelegate.java:476)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLDelegate.handshakeReceiveAndUnWrap(AsyncSSLDelegate.java:395)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLDelegate.doHandshakeImpl(AsyncSSLDelegate.java:294)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLDelegate.doHandshakeNow(AsyncSSLDelegate.java:262)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLDelegate.connect(AsyncSSLDelegate.java:233)
at jdk.incubator.httpclient/jdk.incubator.http.AsyncSSLConnection.connect(AsyncSSLConnection.java:78)
at jdk.incubator.httpclient/jdk.incubator.http.Http2Connection.<init>(Http2Connection.java:272)
at jdk.incubator.httpclient/jdk.incubator.http.Http2ClientImpl.getConnectionFor(Http2ClientImpl.java:108)
at jdk.incubator.httpclient/jdk.incubator.http.ExchangeImpl.get(ExchangeImpl.java:86)
at jdk.incubator.httpclient/jdk.incubator.http.Exchange.establishExchange(Exchange.java:257)
at jdk.incubator.httpclient/jdk.incubator.http.Exchange.responseImpl0(Exchange.java:268)
at jdk.incubator.httpclient/jdk.incubator.http.Exchange.responseImpl(Exchange.java:245)
at jdk.incubator.httpclient/jdk.incubator.http.Exchange.response(Exchange.java:121)
at jdk.incubator.httpclient/jdk.incubator.http.MultiExchange.response(MultiExchange.java:154)
at jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl.send(HttpClientImpl.java:234)
at com.us.HttpRequestTest.shouldReturnStatusOKWhenSendGetRequest(HttpRequestTest.java:35)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
我启用了参数 -Djavax.net.debug = all 的详细调试消息,我收到的日志是:
Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring obsoleted cipher suite: SSL_RSA_WITH_DES_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DHE_RSA_WITH_DES_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DHE_DSS_WITH_DES_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DH_anon_WITH_DES_CBC_SHA
Ignoring obsoleted cipher suite: SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
Ignoring obsoleted cipher suite: SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
Ignoring obsoleted cipher suite: TLS_KRB5_WITH_DES_CBC_SHA
Ignoring obsoleted cipher suite: TLS_KRB5_WITH_DES_CBC_MD5
Ignoring obsoleted cipher suite: TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
Ignoring obsoleted cipher suite: TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
%% No cached client session
update handshake state: client_hello[1]
upcoming handshake states: server_hello[2]
*** ClientHello, TLSv1.2
RandomCookie: random_bytes = {9C CA 88 05 6E 9C 04 57 09 CB 84 92 A4 1D 83 2A 1F E7 34 A7 AB E2 E4 9C 7F 5B 0F 95 04 B0 A7 C5}
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_DH_anon_WITH_AES_256_GCM_SHA384, TLS_DH_anon_WITH_AES_128_GCM_SHA256, TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_ECDH_anon_WITH_AES_256_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_NULL_SHA256, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_anon_WITH_NULL_SHA, SSL_RSA_WITH_NULL_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension status_request_v2
CertStatusReqItemV2: ocsp_multi, OCSPStatusRequest
ResponderIds: <EMPTY>
Extensions: <EMPTY>
CertStatusReqItemV2: ocsp, OCSPStatusRequest
ResponderIds: <EMPTY>
Extensions: <EMPTY>
Extension status_request: ocsp, OCSPStatusRequest
ResponderIds: <EMPTY>
Extensions: <EMPTY>
Extension application_layer_protocol_negotiation, protocol names: [h2][http/1.1]
main, WRITE: TLSv1.2 Handshake, length = 296
[Raw write]: length = 301
0000: 16 03 03 01 28 01 00 01 24 03 03 9C CA 88 05 6E ....(...$......n
0010: 9C 04 57 09 CB 84 92 A4 1D 83 2A 1F E7 34 A7 AB ..W.......*..4..
0020: E2 E4 9C 7F 5B 0F 95 04 B0 A7 C5 00 00 8C C0 2C ....[..........,
0030: C0 2B C0 30 00 9D C0 2E C0 32 00 9F 00 A3 C0 2F .+.0.....2...../
0040: 00 9C C0 2D C0 31 00 9E 00 A2 C0 24 C0 28 00 3D ...-.1.....$.(.=
0050: C0 26 C0 2A 00 6B 00 6A C0 0A C0 14 00 35 C0 05 .&.*.k.j.....5..
0060: C0 0F 00 39 00 38 C0 23 C0 27 00 3C C0 25 C0 29 ...9.8.#.'.<.%.)
0070: 00 67 00 40 C0 09 C0 13 00 2F C0 04 C0 0E 00 33 .g.@...../.....3
0080: 00 32 C0 08 C0 12 00 0A C0 03 C0 0D 00 16 00 13 .2..............
0090: 00 FF 00 A7 00 A6 00 6D C0 19 00 3A 00 6C C0 18 .......m...:.l..
00A0: 00 34 C0 17 00 1B 00 3B C0 06 C0 10 00 02 C0 01 .4.....;........
00B0: C0 0B C0 15 00 01 00 1F 00 23 01 00 00 6F 00 0A .........#...o..
00C0: 00 16 00 14 00 17 00 18 00 19 00 09 00 0A 00 0B ................
00D0: 00 0C 00 0D 00 0E 00 16 00 0B 00 02 01 00 00 0D ................
00E0: 00 1C 00 1A 06 03 06 01 05 03 05 01 04 03 04 01 ................
00F0: 04 02 03 03 03 01 03 02 02 03 02 01 02 02 00 11 ................
0100: 00 10 00 0E 02 00 04 00 00 00 00 01 00 04 00 00 ................
0110: 00 00 00 05 00 05 01 00 00 00 00 00 10 00 0E 00 ................
0120: 0C 02 68 32 08 68 74 74 70 2F 31 2E 31 ..h2.http/1.1
[Raw read]: length = 7
0000: 15 03 01 00 02 02 28 ......(
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1.2 ALERT: fatal, handshake_failure
main, fatal error: 40: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
main, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
答案 0 :(得分:5)
调试日志显示ClientHello中不包含server_name
扩展名(SNI)。但是,根据SSLLabs,该站点在没有SNI的情况下失败。
这似乎是Java 9中此API的已知问题。请参阅错误报告TLS SNI in new Java 9 client is not available以及可能的解决方法Glorious hack to use Java 9 HttpClient with servers enforcing SNI Raw。