Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 接收SSLHandshakeException:尽管我的客户端忽略了所有证书,但握手失败_Java_Ssl_Jboss7.x - Fatal编程技术网

Java 接收SSLHandshakeException:尽管我的客户端忽略了所有证书,但握手失败

Java 接收SSLHandshakeException:尽管我的客户端忽略了所有证书,但握手失败,java,ssl,jboss7.x,Java,Ssl,Jboss7.x,我有一个Java程序,它使用SSL/TLS连接到Web服务器,并通过该连接发送各种HTTP请求。服务器是本地主机,使用自签名证书,但我的代码使用自定义信任管理器,并忽略无效证书。到目前为止,它一直运作良好 服务器上唯一的区别是它过去运行jboss 6,现在运行jboss 7。我不确定这是否是配置问题,或者我的代码是否有问题,但如果我尝试使用其他基于Java的程序(如WebScarab或ZAP)进行连接,我会遇到同样的错误 在任何情况下,我能对我的代码做些什么来解决这个问题吗?以下是完整的错误:

我有一个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

您看到这个错误很可能是因为JBoss 6可以访问的密钥库不能被JBoss 7实例访问

我的建议如下

必须将自签名服务器证书导入信任库

keytool -import -alias gridserver -file server.crt -storepass $YOUR_PASSWORD_HERE -keystore server.keystore
将以下属性添加到run.conf

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=server.keystore
-Djavax.net.debug=ssl # very verbose debug. Turn this off after everything looks good.
-Djavax.net.ssl.keyStorePassword=$YOUR_PASSWORD_HERE
-Djavax.net.ssl.trustStorePassword=$YOUR_PASSWORD_HERE

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

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

如果这不起作用,请使用更多信息(以及完整的堆栈跟踪)更新帖子。

您应该启用ssl调试信息
-Djavax.net.debug=ssl

堆栈跟踪来自您的客户端代码,并且您的客户端“收到[a]致命警报”。换句话说,SSL错误发生在Jboss中,而不是您的客户端

因此,客户端自定义信任管理器与此无关。我的猜测是,您的新JBoss7配置为需要客户端证书,而您的客户端没有提供任何证书

要调试SSL连接,请使用openssl并尝试以下操作:

openssl s_客户端-连接jboss.server.com:443

或者它是一个SSLV3服务器

openssl s_客户端-connect jboss.server.com:443-ssl3


这会打印出很多有趣的信息。

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

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

SSLContext sslContext = SSLContext.getInstance("TLS");
解决方案是在进行任何连接尝试之前设置系统属性:

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

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

我认为这与。没有更多的细节很难确定。这有没有解决过

我遇到了完全相同的问题,基本上我在clientHello之后立即收到了一个握手异常。因此,一连串的事件发生了

  • 我将向服务器出示我的证书
  • 服务器将立即响应握手失败。(我甚至连一个服务器的Hello都找不回来)
  • 最终,我发现服务器需要比我在初始握手阶段提供的加密/解密算法更强的加密/解密算法(即,客户端和服务器无法就用于ssl通信的相互加密算法达成一致)

    我需要安装无限制Java JCE(Java加密扩展策略)。使用这个有导出规则,所以如果你将代码发送到海外,可能会有影响。然而,这就是解决我问题的方法

    此链接说明如何安装更新的策略

    这也是一个很好的链接,帮助我准确地理解了发生了什么


    这可能是问题所在,也可能不是问题所在,但当握手在客户端打招呼后立即失败时,客户端和服务器似乎无法就某些问题达成一致(在许多情况下,这是他们相互需要通信的加密算法)。

    对于我来说,解决方案是:
    System.setProperty(“https.protocols”,“TLSv1.1,TLSv1.2”);

    通过Chrome或Firefox等web浏览器,服务器运行正常,因此服务器上的密钥库不是问题所在。认证也不应该成为问题,因为我只是忽略了所有的证书。完整的堆栈跟踪只显示了我的类的连接方法,以及任何调用它的方法。它与以前版本的服务器使用的方法相同。无论如何,这里是调试:对我来说似乎有点奇怪的是,即使我告诉我的程序使用TLS,它似乎想要发送SSLv2客户机hello消息。对我来说,这里也面临类似的问题细节-我们如何识别这个解密错误?我的猜测就是,wild。你的服务器很好。用户384706使您走上了正确的轨道。这更可能是协议版本不匹配。我看到你的服务器是TLSv1/SSLv3,你似乎在发送SSLv2。@布鲁诺:是的,我之前在搜索谷歌时看到过。这是Java中的一个bug吗?当我将SSLContext指定为TLS时,我看不出它怎么可能/应该是默认行为。这不是一个bug,它是经过设计的(SSLv2是用于向后编译的)。请参阅:“例如,getInstance(“SSLv3”)可能会返回一个实现“SSLv3”和“TLSv1”[…]的实例。您可以使用setEnabledProtocols(String[]protocols)方法控制为SSL连接实际启用了哪些协议。”。在您的例子中,
    https.protocols
    负责
    HttpsURLConnection
    setEnabledProtocols
    。对,但这并不能解释为什么当我要求它使用TLS时,它会尝试使用SSLv2客户端hello消息。服务器只支持TLSv1(特别是),从调试消息来看,它看起来像是Java在切换回之前启动了TLSv1握手