Java 的证书信任问题求解。

2016-02-03 18:30:28 +08:00
 realpg
近日服务器开始启动全线 HTTPS 加密。
采用了 Let's Encrypt 的证书,根证书是 DST Root CA X3 。

我的 Android 程序大多是用 Java 8 编译的,默认就信任这个根证书

然后这两天改一个之前写的 Java 程序,然后发现 JDK7 并不信任 DST Root CA X3

此程序界面是 Swing 的,原开发基于 JDK7 ,升级到 JDK8 , Swing 的 Error 满天飞,只得放弃升级。

通信部分采用 Apache HttpClient , 我知道 HC 是可以在链接时指定服务器证书,添加证书信任的,但是 Let's Encrypt 的证书只给 3 个月有效期,而且内部通信有大量不同的域名不同的证书。总不能一个证书到期就重新编译一次程序,或者更新一次证书吧。

所以我想有没有办法在 Runtime 阶段,添加一个指定 CA 的信任?毕竟 CA 证书有效期长且不变。随便 google 了一下,都是提前在客户端 jre 用命令行维护本地 keystore ,把 CA 加入本地 keystore ,这种对白痴用户太麻烦了。
5382 次点击
所在节点    程序员
21 条回复
yangff
2016-02-03 18:39:19 +08:00
内部用的?自己签嘛。。
wy315700
2016-02-03 18:39:46 +08:00
把根证书加进去
realpg
2016-02-03 18:47:02 +08:00
@wy315700
我 google 的结果,根证书只能加入本地的 jre keystore ,用命令行指令

在代码中添加证书信任, google 到的结果并测试通过的只有把服务器当前的证书加入,这个操作可以代入根证书而不是当次连接的证书么?
wy315700
2016-02-03 18:59:46 +08:00
@realpg
自己的 APP 的话 自己签一个 20 年的证书丢进去其实就行了,,
realpg
2016-02-03 19:05:00 +08:00
@wy315700
不只是自己的 APP
有 APP 有 web 有客户端 有触摸屏 还有公众访问
realpg
2016-02-03 19:05:53 +08:00
@wy315700
使用 let's encrypt 是因为逗比客户不给钱买证书……
现在被劫持的比较厉害
wy315700
2016-02-03 19:07:14 +08:00
@realpg
证书都不给买,,,
,,,活该被劫持
realpg
2016-02-03 19:10:43 +08:00
@wy315700
对公的项目,事儿比较多,合同案值进第三方担保户里之后再申请一分钱都得去财政审批,没戏的。
wy315700
2016-02-03 19:15:58 +08:00
@realpg 我一般给他们用 wosign ,,,
7654
2016-02-03 19:17:54 +08:00
写个脚本自动做啊
realpg
2016-02-03 19:32:10 +08:00
@wy315700
收费不收费再说,域名太多。一个个申请不起。
Let's Encrypt 好歹是自动化的。
项目早就做完了的,这是改,都找不到人了才折腾我头上帮忙。
kaneg
2016-02-03 22:01:46 +08:00
如果客户端代码是自己写的,可以设置信任所有证书(当然安全自负了)。我以前用 apache 的 http client 做过,如果楼主需要我明天找找那段代码发给你
realpg
2016-02-03 22:06:29 +08:00
@kaneg
谢谢,这个我会的。
sslSF.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
但是不能这么写。
我说了劫持很严重,这里面有问题,不敢这么信任

我发这个贴就是想问问,有没有 runtime 临时信任一个根证书的方法
vibbow
2016-02-04 05:59:46 +08:00
记得好像可以手动指定一个 keystore
kaneg
2016-02-04 22:02:37 +08:00
@realpg
你这个是是否校验 hostname ,如果证书链不被信任,还是无法通过的。你要有选择性的信任一个或多个证书链,可以参考以下方式:

SSLSocketFactory mysf = new SSLSocketFactory(new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//这里检验你的证书链是否被信任
return false;
}
});
Scheme https = new Scheme("https", 443, mysf);
client.getConnectionManager().getSchemeRegistry().register( https);
realpg
2016-02-04 22:11:28 +08:00
@kaneg
sslSF.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
事实上,这段代码现在就存在于我的 JAVA 程序内,只要注释掉就报错,恢复程序就能正常使用。
看 ALLOW_ALL_HOSTNAME_VERIFIER 是效验域名,实际上,加上这个,我这里就根本不检测证书链了直接无报错了
wql
2016-02-05 11:06:46 +08:00
建议改用 Start SSL
realpg
2016-02-05 11:20:15 +08:00
@wql
一百四十个域名…… StartSSL 上哪搞得过来……
wql
2016-02-05 11:25:26 +08:00
@realpg 那只有收费证书一条路了,或者让他们 startSSL 买一个 59.99 或 199.99 刀的两年无限证书套餐。
realpg
2016-02-05 11:32:57 +08:00
@wql
今年春节申请 200 块钱
明年春节能给我就不错
折腾个鬼啊……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/255254

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX