jdk1.6 发送Https请求报错,Received fatal alert: handshake_failure

代码如下
SSLContext sslContext=SSLContext.getInstance("SSL");
TrustManager[] tm={new MyX509TrustManager()};
sslContext.init(null, tm, new java.security.SecureRandom());;
SSLSocketFactory ssf=sslContext.getSocketFactory();
//https需要的配置-----------------------------------------
URL realUrl = new URL(url);
// 打开和URL之间的连接
//URLConnection conn = realUrl.openConnection();
HttpsURLConnection conn=(HttpsURLConnection)realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("content-type", "application/json");
 
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(ssf);
conn.connect();
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
String line;
while ((line = in.readLine()) != null) {
    resultSb.append(line);
}
 

出现这个问题的原因主要是因为,客户端与服务端所支持的TLS协议版本不一致。

经过抓包分析,发现jdk6所使用的TLS版本为SSLv3,而对方服务器并不支持这个版本。

所以这个问题有以下几个解决方案。

1.将JDK6升级到8以上的版本

2.和服务器端进行沟通,看对方能否开启对SSLv3的支持。

3.使用第三方的Bouncy Castle

具体可以参考下面这篇文章

https://blog.csdn.net/lizo_is_me/article/details/52490368

4.网上资料说这个应该是旧版本jdkjce中安全机制的bug,要去oracle官网下载对应的jce包替换jdk中的jce包
jce所在jdk的路径: %JAVA_HOME%\jre\lib\security里的local_policy.jar,US_export_policy
.jarJDK7 http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-
432124.html JDK8 http://www.oracle.com/technetwork/java/javase/downloads/jce
8-download-2133166.html        (亲测可行)
                        
原文链接:https://blog.csdn.net/qq_41932089/article/details/108862082

<think>好的,我现在需要帮助用户解决Java中遇到的SSLHandshakeException: Received fatal alert: handshake_failure错误。首先,我要理解这个问题的背景和可能的原因。根据用户提供的引用信息,错误通常发生在SSL/TLS握手过程中,导致连接失败。常见原因包括协议版本不匹配、证书问题、密码套件不支持以及JDK版本问题。 首先,我需要回顾用户提供的引用内容。引用[4]提到JDK 7默认支持TLS版本较低,而JDK 8支持TLSv1.2。如果客户端或服务器使用的JDK版本过低,可能无法协商出双方都支持的TLS版本,从而导致握手失败。另外,用户提到在另一台电脑使用JDK 1.8.0_321成功,而失败的电脑使用JDK 1.8.0_152,切换至JDK 11解决了问题,这可能是因为较新的JDK版本支持更多的TLS协议或修复了相关的问题。 接下来,我需要考虑证书问题。引用[2]指出证书链不完整、自签名证书或证书过期都可能导致握手失败。例如,如果服务器证书未被客户端信任,或者中间证书缺失,客户端会拒绝连接。解决方案可能涉及导入证书或配置信任库。 密码套件也是一个重要因素。客户端和服务器需要支持至少一个共同的密码套件。如果服务器只支持较新的套件,而客户端JDK版本较旧,可能无法匹配。这时需要更新JDK或手动配置支持的套件。 此外,引用[4]提到可以通过代码指定TLS版本,例如使用SSLConnectionSocketFactory明确设置TLSv1.2。这可能绕过协议版本不兼容的问题,尤其是在旧版JDK中强制使用更高版本的TLS。 现在,我需要将这些信息组织成清晰的步骤,帮助用户逐步排查问题。首先检查JDK版本,建议升级到较新版本,如1.8.0_321JDK 11。然后验证TLS协议支持,确保客户端和服务器使用兼容的版本,如TLSv1.2。接下来检查证书有效性,使用工具如OpenSSL或keytool确认证书链完整且受信任。如果问题仍然存在,可能需要配置SSLContext或调整密码套件设置。 同时,用户可能不太熟悉如何具体操作这些步骤,所以需要给出具体的命令或代码示例,例如如何导出服务器证书,如何配置SSLContext等。另外,引用中提到的两种解决方法(升级JDK或指定TLS版本)需要详细说明,帮助用户选择适合他们环境的方案。 最后,生成相关问题时要覆盖用户可能进一步询问的方向,例如如何检查支持的TLS版本、如何更新Java中的信任库、不同JDK版本对TLS的支持差异,以及SSLContext的具体配置方法。这些问题可以帮助用户深入理解并彻底解决问题。</think>### Java中SSLHandshakeException: handshake_failure的原因及解决方法 #### 一、核心原因分析 1. **协议版本不兼容** - JDK版本过低(如JDK 7默认仅支持TLSv1.0),而服务器可能要求更高版本(如TLSv1.2)。例如: $$ \text{JDK 1.8.0_152} \rightarrow \text{默认支持TLSv1.2} \quad \text{vs} \quad \text{JDK 11} \rightarrow \text{支持TLSv1.3} $$ 若客户端JDK版本过低,协议协商失败会导致握手终止[^4]。 2. **证书问题** - 服务器证书链不完整、自签名证书未受信任或证书过期,例如: `keytool -list -v -keystore cacerts` 发现证书缺失或状态异常[^2]。 3. **密码套件不匹配** - 客户端与服务器无共同支持的加密算法(如AES-GCM、ECDHE_RSA等),导致握手失败。 4. **环境配置差异** - 同一应用在不同JDK版本(如1.8.0_152 vs 1.8.0_321)表现不同,可能与安全补丁或协议支持更新有关[^3]。 --- #### 二、解决方案步骤 1. **升级JDK版本** - 优先升级到JDK 1.8.0_321JDK 11+,确保支持现代TLS协议[^4]。 2. **强制指定TLS版本** 在代码中显式配置TLSv1.2(适用于旧版JDK): ```java SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE); ``` 3. **修复证书问题** - 导出服务器证书并导入客户端信任库: ```bash openssl s_client -connect example.com:443 > server.crt keytool -import -alias example -keystore $JAVA_HOME/jre/lib/security/cacerts -file server.crt ``` 4. **检查密码套件兼容性** 使用`nmap --script ssl-enum-ciphers -p 443 example.com`验证服务器支持的套件是否与客户端匹配。 --- #### 三、验证方法 1. **诊断工具** - 通过`java -Djavax.net.debug=ssl:handshake ...`输出握手日志,定位失败阶段。 2. **在线检测** 使用[SSL Labs测试工具](https://www.ssllabs.com/ssltest/)分析服务器配置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_深巷的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值