SSLv2Hello – javax.net.ssl.SSLException:收到致命警报:unexpected_message

我试图在基于Java 6(更新31)的客户端上调用在JDK7 / WildFly 8.2上运行的受SSL保护的Web服务。

我在客户端遇到的第一个问题是:

javax.net.ssl.SSLException:收到致命警报:unexpected_message

通过将javax.net.debug设置为双方的all ,我在服务器端得到以下提示:

javax.net.ssl.SSLHandshakeException:已禁用SSLv2Hello

快速研究表明 ,

默认情况下,客户端上禁用SSLv2Hello:在Java SE 7中,SSLv2Hello将从客户端上的默认启用协议列表中删除。

所以我试图在standalone.xml SSLv2Hello上启用SSLv2Hello

  

而服务器上的结果是:

javax.net.ssl.SSLHandshakeException:没有合适的协议(协议被禁用或密码套件不合适)

所以我意识到,我应该尝试在客户端强制使用TLS,而不是在服务器上启用SSLv2Hello 。 我试图设置System.setProperty("https.protocols", "TLSv1"); 在我的Web服务调用之前没有任何效果。

我应该配置什么以及如何使握手工作?

我从服务器上的默认SSLSocketFactory打印了受支持的密码套件:

 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_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV 

您无需在服务器上启用SSLv2。 您需要在客户端 禁用 SSLv2Hello 协议,方法是从启用的TLS协议中删除SSLv2Hello 并保留其他协议:

 System.setProperty("https.protocols", "TLSv1,TLSV1.1,TLSV1.2"); 

也许SSLv3如果让它变得快乐:它将不会持续更长时间,所以尽量不要这样做。

请注意,它是伪协议。 它不是SSLv2,它是允许某些可以说是破坏的服务器接受hello的兼容性措施。 然而,该会话在SSLv3或更高版本上运行。 它也是过时的。

您可以在JVM上启用SSLv2协议,但这是非常不可取的,因为这是一个严重的安全风险。

客户端使用过时且不安全的协议,应更新为TLSv1.1或TLSv.1.2。 这至少需要Java 7,但是罗伯特提到的Java 8会更好。

更多信息可以在https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https找到,包括按版本支持TLS协议的表。