HTTPS 这个玩意吧,说实话,以前我们项目里不怎么用,反正测试环境也没人关心安全证书那一套。但是现在形势变了,尤其是在各种合规要求日益严格的情况下,连接口请求都得走“加密通道”——也就是 HTTPS。
那问题来了,Java 里怎么调用 HTTPS 接口?我这边总结了两种常见的方式——一个是“图省事式”,直接绕过 SSL 验证,另一个是“正规军”,走证书认证流程。下面咱们按踩坑顺序讲。
先说结论:第一种方式只适合临时调试,第二种才是你上线环境必须要上的正解。
有次我刚接手一个老系统,要接一个外部的支付平台,对方接口是 HTTPS 的,我一看代码,直接 HttpsURLConnection,再一看:居然自定义了一个 X509TrustManager 把所有的证书验证逻辑都“吃掉”了——啥也不验证,啥都信...
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) {}
}
};
这玩意咋说呢,能用是能用,发请求也没报错,结果到了生产一跑就挂——对方服务器启用了强校验,必须验证证书链,结果我们这边就被 SSLHandshakeException 直接踹出来了。
所以说,这种方式,只适合你本地调试玩一玩。真的,上线千万别这么搞——你绕过的是证书验证,也是对用户隐私和数据传输安全的最后一道防线。
那咋整呢?用证书啊,正规流程来一遍。
其实流程也不复杂,主要分三步:拿证书、安装证书、用默认机制调用。
先说第一步——怎么拿证书。其实也不需要什么高级工具,你就用浏览器打开目标接口的地址,然后点地址栏的小锁标志,能看到证书详情,导出 .crt 文件就完事了。我们当时就是连着点了几下“查看证书”然后“导出”,搞定一张 zhengzhoubus.crt。
第二步是安装证书。你得让 JVM 信任这个证书才行,不然还是会报 SSL 异常。安装命令是用 keytool,Java 自带的命令行工具:
keytool -import -alias zhengzhoubus \
-keystore $JAVA_HOME/jre/lib/security/cacerts \
-file /path/to/zhengzhoubus.crt -storepass changeit
注意,changeit 是默认的 keystore 密码,如果你们的系统改过这个密码,那可得问问你们的安全团队,别盲改。
第三步就简单了,回到 Java 代码,你不需要写什么 TrustManager 了,直接让 JVM 走默认的 SSL 验证流程就行了:
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
注意别像我当时那样,一边装了证书一边还保留自定义 TrustManager,那根本没用,JVM 还是会用你自定义的信任策略,等于啥也没干。
另外还有个小细节,我们调用的接口是 POST 的,带 JSON 请求体,这种场景下别忘了设置 Content-Type:
connection.setRequestProperty("Content-Type", "application/json");
有一次我忘了加这行,对方接口返回 400 Bad Request,我还以为 JSON 格式错了,结果查了半天才发现是头没设置对。
整个调用流程下来,其实跟普通的 HTTP 调用没太大差别,除了 SSL 的事需要额外注意。
哦对了,还有一个坑别忘了说,有的服务器用了自签名证书,即使你按上面步骤装进 cacerts 里了,还是会报错。原因是 JVM 的默认信任链没包含这个自签 CA。这时候你得检查一下证书链是不是完整的,如果不完整得自己合成一张 full-chain 的证书再导入。
最后提一句,如果你们公司用的是 SpringBoot,那可以考虑用 RestTemplate 配合 HttpComponentsClientHttpRequestFactory 和自定义 SSLContext,更现代化一点,代码也更清晰。但底层原理其实还是一样的,关键在于怎么构造这个 SSLContext 和信任策略。
总结下来,这事儿其实不复杂,但要做好确实得注意细节。开发阶段想快点调试 OK,可以临时跳过证书验证,但只要进到生产,建议所有人都别嫌麻烦,老老实实把证书装好,走合规流程。等哪天真被安全审计一查,你就知道省这点事儿根本不值当。
你们项目里 HTTPS 调用是怎么做的?是走默认证书机制,还是还在用“信所有证书”那种写法?有没有被线上环境打脸的经历?欢迎来聊聊。

2269

被折叠的 条评论
为什么被折叠?



