接收SSLHandshakeException:尽管我的客户忽略了所有证书,但handshake_failure

2022-09-02 12:23:19

我有一个Java程序,它使用SSL / TLS连接到Web服务器,并通过该连接发送各种HTTP请求。服务器是本地主机,并且使用自签名证书,但我的代码使用自定义信任管理器,并忽略无效的证书。到目前为止,它一直完美地工作。

服务器上唯一的区别是它曾经运行jboss 6,现在运行jboss 7。我不确定这是否是配置问题,或者我的代码是否存在问题,但是如果我尝试使用其他基于Java的程序(如WebScarab或ZAP)进行连接,我会收到相同的错误。

无论如何,我可以对我的代码做些什么来解决这个问题吗?以下是完整的错误:

Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)

以下是失败前的调试消息:

main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure

答案 1

所以我找到了问题所在。Java 中可能存在错误,但客户端似乎启动了 TLSv1 握手,但随后发送了 SSLv2 客户端问候消息,此时服务器拒绝连接。

即使您使用 TLS 实例创建 SSLContext,也会发生这种情况:

SSLContext sslContext = SSLContext.getInstance("TLS");

解决方案是在进行任何连接尝试之前设置系统属性:

System.setProperty("https.protocols", "TLSv1");

可能还有其他解决方案,但这个对我有用。


答案 2

您提供的信息以及您的堆栈跟踪都非常少。
我在这里猜一猜。
我怀疑的是,在新服务器中,协议是TLSv1,而您的客户端尝试与SSLv3(或更少)连接,结果握手失败。

更改客户端以使用更高版本的 TLS 或
使 Web 服务器也支持 SSLv3。我知道如何在Tomcat中做到这一点,但在JBoss中却不知道。

如果这不起作用,请使用更多信息(和完整的堆栈跟踪)更新帖子。
您应该启用 SSL 调试信息-Djavax.net.debug=ssl