HTTPS 通信失败,jdk 1.6(32 位客户端)与 jdk 1.8(64 位)服务器:读取:未知 3.3 警报,长度 = 2

Posted

技术标签:

【中文标题】HTTPS 通信失败,jdk 1.6(32 位客户端)与 jdk 1.8(64 位)服务器:读取:未知 3.3 警报,长度 = 2【英文标题】:HTTPS communication failed , jdk 1.6 (32 bit client) with jdk 1.8 (64 bit) server : READ: Unknown-3.3 Alert, length = 2 【发布时间】:2017-06-15 15:42:59 【问题描述】:

这是我关于***的第一个问题。我正在尝试两个 tomcat 之间的 HTTPS 通信:

    客户端Tomcat,使用JDK1.6 32位。 服务器Tomcat,使用JDK1.8 64位。

HTTPs 请求的客户端代码:

HttpClient hc = new HttpClient();
hc.startSession(monitAppURL);
int code = hc.executeMethod(poster);

我得到的异常:

收到致命警报:handshake_failure

我通过使用-Djavax.net.debug=ssl:handshake:verbose 启动JVM 获得更详细的异常:

触发 SecureRandom 的播种 完成播种 SecureRandom 允许不安全的重新协商:true 允许遗留问候消息:true 是初始握手:true 是否安全重新协商:是的 监控服务@dealy::nap 30::30, setSoTimeout(0) 调用 监控服务@dealy::nap 30::30, setSoTimeout(0) 调用 %% 没有缓存的客户端会话 *** ClientHello, TLSv1 RandomCookie: GMT: 1468994533 bytes = 100, 134, 165, 203, 220, 40, 175, 72, 89, 189, 99, 104, 208, 177, 19, 59, 234, 210, 59、1、57、254、73、155、253、82、102、221 会话 ID: 密码套件:[SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_RC4_128_SHA,TLS_RSA_WIT _AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CB _SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE DSS_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_DES_CBC_SHA,SSL_DHE_RSA_WITH_DES_CBC_S A,SSL_DHE_DSS_WITH_DES_CBC_SHA,SSL_RSA_EXPORT_WITH_RC4_40_MD5,SSL_RSA_EXPORT WITH_DES40_CBC_SHA,SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,SSL_DHE_DSS_EXPORT_W TH_DES40_CBC_SHA,TLS_EMPTY_RENEGOTIATION_INFO_SCSV] P>

压缩方法: 0

*** 监控服务@dealy::nap 30::30, WRITE: TLSv1 Handshake, length = 75 监控服务@dealy::nap 30::30, WRITE: SSLv2 client hello message, length = 101 监控服务@dealy::nap 30::30, READ: Unknown-3.3 Alert, length = 2 监控服务@dealy::nap 30::30, RECV TLSv1 ALERT: fatal, Handshake_failure 监控服务@dealy::nap 30::30,调用closeSocket() 监控服务 @dealy::nap 30::30,处理异常:javax.net.ssl.SSLHan shakeException:收到致命警报:handshake_failure

我已经用set JAVA_OPTS="-Dhttps.protocols="TLSv1" -Djdk.tls.client.protocols="TLSv1" -Dcom.sun.net.ssl.checkRevocation=false -Ddeployment.security.TLSv1=true -Djavax.net.debug=ssl:handshake:verbose -Dsun.security.ssl.allowUnsafeRenegotiation=true -Djdk.tls.enableRC4CipherSuites=true -Ddeployment.security.TLSv1=true -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA启动了我的JVM

但仍然无法摆脱错误。我已经花了很多时间。请帮我解决这个问题。

【问题讨论】:

您能否升级您的客户端 tomcat 实例以使用 JDK 1.7?我发现 JDK1.6 与 TLS1 存在问题 不,我不能升级 jdk 1.6,因为它是一个遗留应用程序。通信在 HTTP 上工作,但在 HTTPS 上失败 【参考方案1】:

我找到了解决问题的方法, 1.发生了什么事? Java 6 默认使用 SSlv2Client Hello 消息进行握手,即使它使用 TLSv1 协议。握手消息格式是 sslv2Client hello

@dealy::nap 30::30, WRITE: SSLv2 client hello message,length=101

我的服务器使用的是 java 8,出于安全原因禁用了 SSLv3,

jdk.tls.disabledAlgorithms=SSLv3

这导致我的握手消息失败,因为我的客户端正在发送 sslv2Client hello 消息,即使选择了 TLSv1 协议进行通信。它报告为错误:

https://serverfault.com/questions/637880/disabling-sslv3-but-still-supporting-sslv2hello-in-apache

如果你在 jvm 中禁用 Sslv3,它也会禁用 sslv2Client Hello 消息支持

2.我做了什么? apache httpClient默认总是使用jvm原始协议栈进行通信。这就是为什么我的 jvm 参数不适用于 httpclient。

所以,我通过添加以下代码覆盖了 httpclient SSL 通信。

SSLContext sslContext = SSLContexts.custom()
  .useTLS()
  .build();

SSLConnectionSocketFactory f = new SSLConnectionSocketFactory(
  sslContext,
  new String[]"TLSv1",   
  null,
  SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

HttpClient hc = HttpClients.custom()
  .setSSLSocketFactory(f)
  .build();

最后,Apache httpclient 启动了 TLSv1 格式的握手消息进行通信。

我希望这对面临同样问题的人有所帮助,

谢谢。

【讨论】:

请注意,ALLOW_ALL_HOSTNAME_VERIFIER 使您的代码信任所有证书,不推荐这样做。 您正在使用哪个库以 SSLContexts 为特色?

以上是关于HTTPS 通信失败,jdk 1.6(32 位客户端)与 jdk 1.8(64 位)服务器:读取:未知 3.3 警报,长度 = 2的主要内容,如果未能解决你的问题,请参考以下文章

在 Maven 中从 JDK 1.6 升级到 JDK 1.8 时 JUnit 失败,但它在 eclipse 中工作

Java切换JDK版本时遇到的小错误。

32位ODBC数据源,但是jdk是64位的,是否不兼容?

JDK1.6如何安装

为啥我的64位jdk装好后cmd显示32位,怎么改啊

怎么根据自己电脑下载合适jdk,下哪个版本最合适?