【问题标题】:Certificate not being sent sporadically证书不会偶尔发送
【发布时间】:2013-09-20 12:15:33
【问题描述】:

在我的应用程序中,我有 2 个组件通过 REST(基于客户端-服务器)相互通信。
该应用程序可以配置为使用 HTTP 或 HTTPS(自签名证书)。

有时当我在 HTTPS 模式下启动我的应用程序时,我的客户端无法与服务器通信。我收到以下异常:

    09-16-2013 12:28:52 [dispatcher] [http-nio-8143-exec-8] [INFO] - Exception while dispatching request
java.util.concurrent.ExecutionException: com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    ...
Caused by: com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    ...
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    ...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    ...

当我停止并启动应用程序时,一切都按预期工作。
我尝试寻找解决方案,但由于不时发生的事情并通过重新启动修复,找不到与我的问题相似的任何问题,所有问题都是一致的。

Java 版本:Oracle Corporation,“Java HotSpot(TM) 64 位服务器 VM”,1.7.0_17-b02 操作系统:红帽 有什么想法吗?

更新
事实证明,这也可能在应用程序运行一段时间后发生。意思是,一切正常,SSL 通信正常,突然发生此错误,直到我重新启动客户端才能解决。

我能够用 -Djavax.net.debug=all 重现问题,显然证书没有从客户端发送,问题是为什么。由于有时一切顺利,什么会导致事情不时出错?

客户端:

pool-4-thread-2, WRITE: TLSv1 Handshake, length = 48
pool-4-thread-2, waiting for close_notify or alert: state 1
pool-4-thread-2, received EOFException: error
pool-4-thread-2, Exception while waiting for close javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
pool-4-thread-2, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
%% Invalidated:  [Session-7, TLS_RSA_WITH_AES_128_CBC_SHA]
pool-4-thread-2, SEND TLSv1 ALERT:  fatal, description = handshake_failure
Padded plaintext before ENCRYPTION:  len = 32
0000: 02 28 7A 8E 21 1F 09 1A   5F 00 5C 42 6B 12 33 D8  .(z.!..._.\Bk.3.
0010: 73 F0 58 DD 0D D9 09 09   09 09 09 09 09 09 09 09  s.X.............
pool-4-thread-2, WRITE: TLSv1 Alert, length = 32
pool-4-thread-2, Exception sending alert: java.net.SocketException: Broken pipe
pool-4-thread-2, called closeSocket()
Keep-Alive-Timer, called close()
Keep-Alive-Timer, called closeInternal(true)
Keep-Alive-Timer, SEND TLSv1 ALERT:  warning, description = close_notify
Padded plaintext before ENCRYPTION:  len = 32
0000: 01 00 FD 8B FE 50 2A 16   8A FC 10 F7 E0 05 7E D1  .....P*.........
0010: 0A 78 A0 03 84 26 09 09   09 09 09 09 09 09 09 09  .x...&..........
Keep-Alive-Timer, WRITE: TLSv1 Alert, length = 32
[Raw write]: length = 37
0000: 15 03 01 00 20 24 CC 05   7B DA AA 98 D7 BC 49 07  .... $........I.
0010: 59 94 A4 42 A1 D9 22 42   34 C2 75 1B 9E 36 F0 23  Y..B.."B4.u..6.#
0020: 58 9D 80 8D 38                                     X...8
Keep-Alive-Timer, called closeSocket(selfInitiated)

服务器端:

http-nio-8243-exec-2, READ: TLSv1 Handshake, length = 269
*** Certificate chain
***
http-nio-8243-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated:  [Session-5, TLS_RSA_WITH_AES_128_CBC_SHA]
http-nio-8243-exec-2, SEND TLSv1 ALERT:  fatal, description = bad_certificate
http-nio-8243-exec-2, WRITE: TLSv1 Alert, length = 2
http-nio-8243-exec-2, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
http-nio-8243-exec-2, called closeOutbound()
http-nio-8243-exec-2, closeOutboundInternal()
http-nio-8243-ClientPoller-1, called closeOutbound()
http-nio-8243-ClientPoller-1, closeOutboundInternal()
http-nio-8243-ClientPoller-1, SEND TLSv1 ALERT:  warning, description = close_notify

【问题讨论】:

    标签: java ssl handshake sslhandshakeexception


    【解决方案1】:
    javax.net.ssl.SSLHandshakeException: null cert chain
    

    看起来服务器需要一个客户端证书,而您没有发送一个,或者发送了一些无效的东西。在客户端 SSL 日志中,您将有一个入站 CertificateRequest,后面没有出站 Certificate 消息,或者后面是一个空消息。

    【讨论】:

    • 事情是运行代码大部分时间都可以工作(发送证书),但有时不能。我不确定有时不加载\发送密钥库的原因是什么。
    • 如您所见,将需要格式化的内容发布为无法格式化的 cmets 是没有意义的,但我在那里没有看到证书消息,这证明了我的观点。
    • 我在问题正文中发布了相同的评论,您可以在其中看到它的格式。正如您所说,很明显客户端不发送证书。我的问题是什么会导致他有时有时不发送证书。意思是,有时在启动客户端时它会发送证书,有时不是,然后重新启动即可解决问题。
    • 投反对票,这个答案显然与有时会发生连接的事实相矛盾。
    • @LaurentCaillette 难以理解。 OP同意这个答案。他补充说“显然,证书不是从客户端发送的”。他给了它50分。他相应地更改了问题的标题。他发布了一个 JSSE 调试跟踪,证明它毫无疑问。他现在提供了导致证书无法发送的代码。
    【解决方案2】:

    显然有人添加了覆盖证书的代码:

            HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
    

    我删除了这一行,现在一切正常。

    【讨论】:

    • 此代码不会“覆盖证书”。它将 SSLContext 更改为无权访问它的内容。
    猜你喜欢
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    相关资源
    最近更新 更多