OpenJDK 17发送HTTPS请求遇SSLHandshakeException握手失败
解决OpenJDK 17.0.1下SSL握手失败问题
我使用OpenJDK 17.0.1向服务器发送GET请求时,持续收到错误:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure。
实现代码
package org.example; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import java.io.FileInputStream; import java.security.KeyStore; public class HttpsGetWithCustomSSLExample { public static void main(String[] args) { try { // 目标API地址 String apiUrl = "https://192.168.14.193:8050/sample-v1"; // 加载信任库 KeyStore trustStore = KeyStore.getInstance("JKS"); try (FileInputStream trustStoreInputStream = new FileInputStream("store/server.truststore")) { trustStore.load(trustStoreInputStream, "WalletPasswd123".toCharArray()); } // 加载密钥库 KeyStore keyStore = KeyStore.getInstance("JKS"); try (FileInputStream keyStoreInputStream = new FileInputStream("store/server.keystore")) { keyStore.load(keyStoreInputStream, "WalletPasswd123".toCharArray()); } // 创建包含自定义信任库和密钥库的SSL上下文 SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial(trustStore, null) .loadKeyMaterial(keyStore, "WalletPasswd123".toCharArray()) .setProtocol("TLSv1.3") .build(); // 创建带SSL上下文的HttpClient CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build(); // 创建GET请求 HttpGet httpGet = new HttpGet(apiUrl); // 执行请求并处理响应 try (CloseableHttpResponse response = httpClient.execute(httpGet)) { int responseCode = response.getStatusLine().getStatusCode(); System.out.println("响应码: " + responseCode); String responseBody = EntityUtils.toString(response.getEntity()); System.out.println("响应内容: " + responseBody); } } catch (Exception e) { e.printStackTrace(); } } }
错误截图

排查与解决方法
检查TLS版本兼容性:代码中强制指定了
TLSv1.3,若服务器不支持该版本会直接握手失败。可以尝试:- 移除
.setProtocol("TLSv1.3"),让JDK自动协商双方支持的最高TLS版本; - 改为指定服务器明确支持的版本,比如
.setProtocol("TLSv1.2")。
- 移除
验证密钥库与信任库有效性:
- 确认
store/server.truststore和store/server.keystore文件路径正确,程序可正常读取; - 用
keytool命令检查证书状态:# 查看信任库证书列表 keytool -list -keystore store/server.truststore -storepass WalletPasswd123 # 查看密钥库证书列表 keytool -list -keystore store/server.keystore -storepass WalletPasswd123 - 确保信任库中包含服务器的CA证书,密钥库中的客户端证书已被服务器信任。
- 确认
检查证书链完整性:服务器证书可能缺少中间证书,导致客户端无法完成验证。需将完整的证书链(根证书+中间证书)导入信任库。
启用SSL调试日志定位问题:添加JVM启动参数
-Djavax.net.debug=ssl,handshake,运行程序后查看详细握手日志,可明确是协议协商失败、证书验证失败还是其他环节出问题。
内容的提问来源于stack exchange,提问作者Pasindu Ukwatta
相关产品推荐
相关产品推荐

