4月9
随着 Java 生态的演进,我们将核心项目从 JDK 8 迁移至 JDK 21。然而,在升级过程中,我们遇到了一个令人费解的现象:原本在 JDK 8 上运行正常的第三方接口调用,在 JDK 21 上却频繁抛出 SSLHandshakeException: Received fatal alert: handshake_failure。本文将详细复盘这次排查过程,揭示 JDK 21 在 SSL/TLS 握手层面的底层变化,并提供终极解决方案。
一、 故障现象:版本升级后的“断连”
在将开发环境切换至 JDK 21 后,我们的应用在调用特定政府网站接口(https://www.xxx.gov.cn)时发生了故障。
错误日志:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
诡异现象:
JDK 8: 运行完美,无任何报错。
JDK 21: 死活连不上,且不报证书错误(CertificateException),直接握手失败。
浏览器/Postman: 可以正常访问。
这种“代码没变,环境变了”的差异,直接指向了 JDK 版本间的底层安全策略差异。
二、 排查之路:层层递进的“破案”过程
为了定位问题,我们开启 -Djavax.net.debug=ssl:handshake 调试模式,通过分析握手日志,我们经历了三个阶段的认知升级。
第一阶段:误判为“弱加密算法” —— 方案失效
直觉: JDK 21 更安全,默认禁用了弱算法。我们猜测是服务器使用了 MD5 或 1024 位密钥。
行动: 修改 java.security 文件,删除 jdk.tls.disabledAlgorithms 中的限制,甚至加上了 ECDH(误以为是禁用了 ECDH 导致的)。
结果: 无效。 即使放宽了所有限制,握手依然失败。这说明问题不在“禁用列表”,而在“协商过程”。
第二阶段:聚焦“椭圆曲线” —— 关键线索
在仔细比对 ClientHello(客户端发起)和 ServerHello(服务器回复)的日志时,我们发现了异常。
在服务器的 ECDHServerKeyExchange 消息中,出现了如下关键字段:

"ECDH ServerKeyExchange": {
  "parameters": {
    "named group": "x448"  // 服务器强制要求使用 x448 曲线
  }
}
分页: 1/1 第一页 1 最后页 [ 显示模式: 摘要 | 列表 ]