浏览器一屏红字,提示证书不受信任,你点开证书详情一看——签发者是 DigiCert,有效期还长得很,怎么看都不像它坏了。这种情况遇到的人太多了。证书信任链报错的时候先别急着重新签、别急着换证书商,八成跟根证书一点关系都没有,问题出在链条中间那一段被你弄丢了。

证书信任链是一条链,不是一张证书
很多人脑子里就一个概念:我有证书,装上去就该是绿的。实际上浏览器验的不是你那一个文件,而是一条从你服务器一路连到它自己信任库里的链路。链条一般三层:你的服务器证书(业内叫叶子证书)在最下面,中间夹一层中间证书(intermediate),最上面才是根证书。根证书是浏览器和操作系统出厂就带好的,你既不用上传也不用配置,它躺在系统信任库里等着被比对。
所以配置的时候,你要交给浏览器的从来不是孤零零一张叶子证书,而是叶子加中间证书这一串。缺了中间那一环,浏览器顺着往上找,找不到下一站的签发者,就直接判定链条断了——报错文案往往写成「无法获取本地颁发者证书」或者「颁发机构无效」,看着特别像根证书的问题,其实是你没给它递中间那一环。
真正要补的都是中间证书
症状很好认。同一个站点,Chrome 打开是绿的,用 curl 一跑就报错,微信里点开白屏或者提示不安全,iOS 上干脆拒绝连接。这类「换个客户端就翻车」的表现,基本可以锁定服务端没发中间证书。有人在 Chrome 上测试通过了就以为万事大吉,那是因为 Chrome 有自己的一套补链机制,会顺着证书里的地址自己去把中间证书抓回来,属于帮你兜底,不是你没配好。
一条命令就能看出来服务端到底发了几个证书:openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts,回车之后屏幕上会列出 Certificate chain 的层级,正常情况下你得看到至少两层,也就是你的证书加一张中间证书。只输出一层、或者干脆显示 no certificate chain,那就别往下猜了,问题就在这。
Nginx 里那个 ssl_certificate 该填哪个文件
这地方是最容易填错的一步,而且错得很隐蔽。证书商给你的压缩包里通常有好几个文件,一个叫你的域名.crt,一个叫 ca_bundle.crt 或者 intermediate.crt,还有一个是私钥。不少人直接把域名.crt 填进 ssl_certificate,中间证书那个文件随手扔在一边没用上。正确的做法是把两者拼成一个文件,顺序不能反——叶子证书在前,中间证书在后,粘贴到一起保存成 fullchain.crt,然后 ssl_certificate 指向它,ssl_certificate_key 指向私钥。顺序反了浏览器照样报错,这个坑踩过的人不少。
Apache 的写法不太一样。老版本用 SSLCertificateFile 放叶子证书、SSLCertificateChainFile 放中间证书,新版本直接把整串放进 SSLCertificateFile 就行。不管你用哪个,配完别图省事只在浏览器里刷一下就算完,用 openssl verify 拿系统根证书库跑一遍,能过才算数。命令里那个根证书库路径各发行版不一样,以你系统里的实际位置为准,拿不准就查一下官方文档。
浏览器好好的,Java 那边却炸了
还有一种特别有迷惑性的情况:网页端一切正常,后端程序调接口时报 PKIX path building failed。这个报错的字面意思和根证书高度相关,于是又有人跑去换根证书。真相通常是 Java 默认不会顺着证书里的地址去自动补链,它拿到的链是断的,就直接不认。解决思路还是那一条——服务端把中间证书发全,别指望客户端替你补。Android 老版本、某些小程序容器、命令行里的 curl,逻辑都跟 Java 类似,该发的链一节都不能省。
几个常被冤枉成根证书的原因
服务器时间跑偏是最常见的一个。证书上有生效时间和失效时间,机器时间差了几天甚至几年,验签就会直接判失败,报错文案照样往信任问题上靠。所以排查时顺手敲一下 date,比对一下当前时间,费不了几秒钟。
再就是 SNI 的问题。老客户端握手时不带域名信息,服务器只能返回默认站点的证书,域名对不上,浏览器就说不受信任。这种情形放到今天不算主流,但老设备、老采集器、某些嵌入式的 HTTP 客户端里还遇得到。还有自签证书——这东西本来就不在系统信任库里,报不受信任是天经地义的,不是配置错了。公司网络里有代理做中间人替换证书的,你看到的签发者会是个陌生的名字,也不是根证书的锅。
至于根证书本身被浏览器厂商移除或者弃用,确实会发生,但这类变动都是公开公告的,什么时候生效、影响哪些证书,以浏览器厂商和服务商的官方页面说明为准。真碰上了,换一张带交叉签名的证书或者干脆换证书商就行,不必自己在家瞎推测。
按这个顺序查,能省一大半时间
第一步永远是看服务端发了什么,openssl s_client 加 -showcerts,数一数链条几层。第二步看顺序对不对,叶子在前中间在后,拼错的文件重新拼。第三步用 openssl verify 配系统根证书库验一遍,同步确认服务器时间。第四步换两个完全不同的客户端对比结果,浏览器、curl、小程序容器随便挑两个。第五步才轮到怀疑根证书,而这一步在实操里被触发的概率低得可怜。
查完这五步还搞不定,就把完整链条和报错原文一起发给证书服务商的技术支持,比自己在论坛里翻半天强。链条这东西不长,但每一环都得在,缺哪一环报错就往哪一环指,别被文案带偏了方向。
【版权声明】:本站内容若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!