手机和操作系统

Trust anchor for certification path not found:安卓报错修法

作者: · 最后核实

报错信息java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

“Trust anchor for certification path not found”的意思是:安卓 App 无法把服务器证书和它信任的任何根证书连起来。 真实场景里,大多数是服务器没有发送中间证书。浏览器会悄悄补上,安卓 App 不会,于是出现“网页正常、App 报错”。

先判断是网站的问题还是你设备的问题

检测报证书链不完整,就是服务器的问题;检测正常,再查设备和网络。用 SSL 检测 查服务器的证书链:

curl ssl.sh/example.com
  • 检测提示证书链不完整、私有 CA 或自签名:要修服务器(私有 CA 则配置 App)。
  • 检测正常:看失败是否只出现在老版本安卓、特定网络(TLS 拦截),或者装了用户 CA 的调试环境里。

开发者可以确认服务器发了什么:

openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \
  | grep -E "^ *[0-9] s:"

只有 0 s: 一行,就说明缺中间证书。

原因

服务器没有发送中间证书是最常见的原因;私有 CA、被忽略的用户 CA、老安卓缺根证书和网络拦截也会导致这个报错。

1. 缺中间证书

服务器只配置了站点证书。改用完整证书链文件,见 缺少中间证书。宝塔面板、云负载均衡上传证书时,“证书”一栏要把中间证书一起粘进去。

2. 私有 CA 或自签名证书

内部接口和测试服务器常用安卓不信任的证书。通过网络安全配置为该域名内置 CA,或者换成公开证书。

3. 用户安装的 CA 被忽略

目标 API 24 及以上的 App 默认忽略用户安装的根证书,见 安卓 App 不信任用户 CA。

4. 老安卓缺根证书

早已停止更新的设备可能没有较新的根证书,见 老安卓和 Let's Encrypt。国内不少老款电视盒子、车机、收银机仍在跑 Android 5、6,最容易遇到。

5. 网络拦截

公司代理和需要认证的公共 Wi-Fi 会出示自己的证书,App 会拒绝。用蜂窝数据测试。

在各浏览器/系统上的样子

场景 显示内容
安卓 App 日志 javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
安卓 Chrome 常常能正常打开网站
服务器上的 Java PKIX path building failed
iOS App NSURLErrorDomain Code=-1202

站长怎么修

1. 发送完整证书链。

ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

CA 给的是分开的文件,就用 证书链工具 生成证书链。

2. 检查 App 用到的每个入口。 API 网关、CDN、负载均衡各有一份证书和证书链。

3. 私有 CA 只针对那个域名把 CA 内置进 App(res/xml/network_security_config.xml 里写 <domain-config> 和 <certificates src="@raw/company_root"/>),绝不要用“信任所有”的 TrustManager。

4. 验证。 用 curl ssl.sh/example.com 检查,并在你支持的最老安卓版本真机上测试。

常见问题

同一台手机上 Chrome 能打开网站,App 为什么失败?

安卓 Chrome 能自动下载缺失的中间证书,还信任用户安装的 CA。用系统默认 TLS 的 App 两样都不做,所以会暴露出被 Chrome 掩盖的证书链问题。

能不能在 App 里直接信任所有证书?

不能。接受一切的 TrustManager 或 HostnameVerifier,会让网络上的任何人都能读取和篡改 App 的流量,Google Play 会对这类实现发出警告,国内应用商店的安全检测通常也会把它列为高危。修服务器证书链,或者只针对特定私有 CA 用网络安全配置。

只有老手机报错,有什么不同?

老版本安卓缺少较新的根证书。比如 Let's Encrypt 使用的 ISRG Root X1,从 Android 7.1.1 起才内置。见 老安卓和 Let's Encrypt。

资料来源

  1. Android Developers:使用网络协议确保安全
  2. Android Developers:网络安全配置
  3. Let's Encrypt: Certificate compatibility