Java 7中使用Bearer Token授权调用HTTPS API时遭遇SSL握手错误的解决方法
这个错误我之前也碰到过,核心原因是Java在验证SSL证书链时,发现证书的时间戳不符合要求——要么是证书过期了,要么是本地系统时间和证书的有效区间不匹配,也可能是证书链里的中间证书出了问题。给你几个一步步排查解决的方案:
排查步骤与解决方法
1. 先检查本地系统时间(最常见原因)
Java会严格校验SSL证书的有效起止时间,如果你的机器系统时间设置错误(比如调到了几年前或者几年后),就会触发这个timestamp check failed错误。先确认运行Java程序的机器的系统时间、时区是否正确,调整到当前真实时间后再重试。
2. 确认目标API的证书是否有效
如果系统时间没问题,那需要检查目标HTTPS API的证书是否在有效期内:
- 用浏览器访问API的URL(比如
https://example-url.com/xxx),点击地址栏的锁图标,查看证书详情,确认“有效起始日期”和“有效截止日期”是否包含当前时间。 - 如果证书已经过期,直接联系API服务方更新证书即可。
3. 修复证书链缺失问题
有时候服务器没有返回完整的SSL证书链,导致Java7的默认信任库无法完成校验。这时候需要把缺失的中间证书导入到Java的信任库中:
- 首先用
openssl命令导出服务器的证书链:
在输出中找到中间证书(不是根证书也不是服务器证书),复制从openssl s_client -connect example-url.com:443 -showcerts-----BEGIN CERTIFICATE-----到-----END CERTIFICATE-----的内容,保存成intermediate.crt文件。 - 然后用
keytool命令将证书导入Java7的信任库(默认路径是$JAVA_HOME/jre/lib/security/cacerts,默认密码是changeit):keytool -import -alias intermediate-cert -file /path/to/intermediate.crt -keystore $JAVA_HOME/jre/lib/security/cacerts
4. 临时绕过SSL校验(仅测试环境使用!)
如果只是在测试环境快速验证功能,不想折腾证书,可以临时禁用SSL校验,但绝对不能在生产环境使用,这会带来严重的安全风险。修改你的代码如下:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.HttpURLConnection; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; import java.security.cert.X509Certificate; import java.security.NoSuchAlgorithmException; import java.security.KeyManagementException; public class HttpURLConnectionExample { public static void main(String[] args) throws Exception { try { // 临时禁用SSL校验(测试用) disableSslVerification(); URL url = new URL("https://example-url.com/xxx"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("Authorization", "Bearer eyXXXXXX"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String output; StringBuffer response = new StringBuffer(); while ((output = in.readLine()) != null) { response.append(output); } in.close(); // printing result from response System.out.println("Response: " + response.toString()); } catch (Exception e) { e.printStackTrace(); } } private static void disableSslVerification() throws NoSuchAlgorithmException, KeyManagementException { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); } }
内容的提问来源于stack exchange,提问作者Joe Harry
相关产品推荐
相关产品推荐

