Apache HttpClient 中的自签名证书问题

Self signed certificate issue in Apache HttpClient

我有一个网站的自签名证书。我使用 keytool 将它导入 java cacert 文件。之后,它可以很好地处理 RestTemplate 请求。 当我使用 Apache HttpClients 请求时,出现如下异常:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    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:123)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
    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:86)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at HttpClientRequestTest.test3(HttpClientRequestTest.java:93)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.junit.runners.model.FrameworkMethod.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.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=10=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.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.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: java.io.EOFException: SSL peer shut down incorrectly

RestTemplate代码:

final RestTemplate restTemplate = new RestTemplate();
final ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

Apache HttpClients 示例:

final HttpGet request = new HttpGet(url);
final HttpClient httpClient = HttpClients.createDefault();
final HttpResponse response = httpClient.execute(request);

有没有人知道为什么它使用 RestTemplate 但不使用 HttpClients?
HttpClient 版本为 4.5.13

当您处理 “任何(!)类型的 'crypto issue,'” 时,您需要查看日志文件,尤其是“从服务器端。”

“客户”当然是故意的,“应该绝对不会学到任何东西”,因为它被假定为“Eve-il 入侵者”,而不是“爱丽丝”或“鲍勃”。客户只感觉到门在他们面前砰的一声关上了,完全没有解释。

没有足够的信息来回答原因。

我们所知道的是终止连接的是服务器。因此,似乎是客户做错了。

这是一个好兆头,因为这意味着您可以采取一些措施:)

您提到了 CA 证书 - 我个人看不出有什么方法可以让您的服务器关心您安装的 CA 证书。这些证书用于验证服务器提供的证书。

您有几个选项可以解决:

一个。调试:使用一个很好的反编译器,比如 IntelliJ 自带的反编译器。您将挖掘到 URL 对象类型,您将看到提供的证书、收到的证书……加密算法……等等…… 如果您不确定这些东西中的任何一个应该是什么,至少将它与“有效的”的调试进行比较。

乙。 TCP 跟踪。根据可用的内容,您可以使用 WireShark 查看数据。可能需要一些手动解密。 同样,与已知的良好值或至少与有效的方法进行比较

C.服务器日志。如果您可以访问这些并且它们很好,异常应该出现在这些日志之一中并告诉您客户端消息有什么问题

D.反复试验。尝试忘记您的假设并更明确地使用您的配置。可能某些东西被设置为默认值,而这不是服务器喜欢的