很多站长第一次遇到 NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM 这个报错时都是懵的:明明网站还能正常打开,为什么 Chrome 突然就拦截了?证书也没过期,配置也没动过,怎么就访问不了呢?等你翻到“高级”按钮点开详情,看到"SHA-1"这个词,大概就明白问题出在哪了——是的,你手上的 SSL 证书还在用十几年前的 SHA-1 签名算法,而主流浏览器从 2017 年开始就一步步收紧了对弱签名的容忍度,直到现在直接亮红牌。
这个报错本身不算复杂,但修复起来牵扯到证书重新签发、服务器配置、证书链处理,还经常遇到“改了证书还是报错”“内部系统不敢动”这类麻烦。这篇文章我按自己的排障经验,从问题识别、根因分析到手工修复、自动化方案,再到常见坑位,一条龙讲清楚。不管你是个人站长、运维,还是被公司遗留系统拖着的老开发,应该都能在里面找到对应的解法。
1. 先搞清楚报错在说什么
1.1 浏览器为什么突然“翻脸”
要理解这个报错,先得知道浏览器在 HTTPS 连接里到底做了什么。你访问一个 HTTPS 网站时,服务器会把自己的证书发给浏览器,浏览器拿到证书后要干三件事:第一,验证证书是不是由受信任的 CA(证书颁发机构)签发的;第二,检查证书是否在有效期内;第三,也是最容易被忽略的——检查证书本身的签名算法是否还在可接受范围内。
前两项是常规体检,第三项算是“政审”。浏览器内置了一份“算法黑名单”,如果你的证书签名算法属于弱算法,比如 SHA-1,就会被判定为“政治不合格”,哪怕证书合法、没过期,也会直接拦截,并给出 NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM 这个错误码。
Chrome 的拦截页面可能长这样:红色感叹号、您的连接不是私密连接、错误代码 NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM。Firefox 也会有类似提示,Safari 更是直接拒绝。如果你用的是 Chrome 66 之后的版本,基本没有“继续访问”的按钮让你绕过去,想用浏览器打开都难。
那这个“签名算法”到底是什么?简单打个比方:证书相当于一张身份证,签名算法就是身份证上的防伪水印。水印做得越复杂,越难伪造;水印技术落后了,监查部门就会强制要求换新证。SHA-1 就是这么一种已经被攻破的水印技术,现在还在用,等于拿着一张旧版身份证到处跑,需要重新换一张了。
1.2 两分钟自查:你的证书签名算法到底是什么
在动手处理之前,先把问题确认清楚。我一般用两种方式检查,都很简单。
第一种,直接用浏览器看。Chrome 地址栏点那个小锁图标 → “连接是安全的” → “证书有效”,在弹出的证书详情窗口里找到“签名算法”或“Signature Algorithm”字段。如果显示的是 sha256WithRSAEncryption,说明签名算法是 SHA-256,属于安全范围,问题不在这里;如果显示 sha1WithRSAEncryption,恭喜你,答案找到了,就是这个 SHA-1 在搞事。
第二种方式更准,也更适合运维用。直接在服务器上跑一句 openssl 命令:
bash复制echo | openssl s_client -connect www.yourdomain.com:443 -servername www.yourdomain.com 2>/dev/null | openssl x509 -noout -text | grep "Signature Algorithm"
输出如果是 Signature Algorithm: sha1WithRSAEncryption,那就基本确认了。注意看证书链上每一级证书的签名算法,有时候叶子证书已经换了 SHA-256,但中间证书还是 SHA-1,同样会报错,这一点后面细说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 根因分析:弱签名算法是怎么一步步被淘汰的
2.1 签名算法在证书体系里的角色
SSL/TLS 证书的本质是把“域名 + 公钥 + 组织信息”打包起来,然后由 CA 用自己的一对公私钥给这个包做个数字签名。这个签名的作用是保证证书内容没有被篡改,也证明这个证书确实是某个受信任 CA 签发的。
整个验证流程是典型的非对称加密:CA 用自己的私钥签名,浏览器用 CA 的公钥验证签名。验证过程其实是在做一次哈希运算加解密校验——先把证书内容做一个摘要(哈希值),然后用签名算法和 CA 的公钥解开签名里的摘要,两边比对,一致就说明证书合法。
这里的关键就在于哈希算法。早期流行的是 SHA-1,后来因为碰撞攻击风险越来越高,逐渐被 SHA-256 取代。签名算法里的“SHA-1”“SHA-256”指的就是这一步用的哈希函数,而不是加密算法本身。加密和签名是两码事,但很多人容易混淆。
顺便提一下,热搜里常能看到“AES-ECB 加密算法”这类词,还有“基础加密算法”的说法,这些经常被放一起讨论。AES 是加解密算法,SHA 是哈希算法,RSA/ECDSA 是签名算法,四者各有归属。证书签名主要用的是“哈希 + 非对称签名”的组合,也就是 SHA-RSA 或 SHA-ECDSA。遇到 ERR_CERT_WEAK_SIGNATURE_ALGORITHM,核心要处理的是哈希这一环,别被一堆同类概念绕晕。
2.2 SHA-1 为什么被拉黑
SHA-1 诞生于 1995 年,在很长一段时间里都是数字签名和完整性校验的标配。但随着算力增长,SHA-1 的碰撞攻击从理论变成了现实。2017 年,Google 和 CWI Institute 联合宣布了全球首个 SHA-1 碰撞实例——两个内容不同但 SHA-1 哈希值完全相同的 PDF 文件被构造出来。这直接宣告了 SHA-1 在对抗场景下的死刑。
之后主流浏览器陆续设置了“禁用开关”。Chrome 从 2017 年 1 月开始对使用 SHA-1 证书的网站显示“不安全”标记,后来一步步收紧到直接拦截。Mozilla 也在 2017 年禁止了新签发证书使用 SHA-1,并要求已在用的证书尽快替换。Microsoft 的 Windows 和 Edge 也加入了限制阵营。到今天,SHA-1 证书在浏览器里基本就是死路一条。
这里要区分一个概念:证书链里可能有“根证书”和“中间证书”。根证书由浏览器厂商内置信任,它们本身一般不受浏览器算法策略的严格限制;但服务器下发的叶子证书和中间证书,如果签名算法是 SHA-1,浏览器就会毫不留情地报错。很多老系统用的还是 2016 年签发的 SHA-1 证书,一直没换,等到浏览器强制拦截的那一天,才不得不处理。
2.3 除了证书,还有哪些弱算法会被拦
ERR_CERT_WEAK_SIGNATURE_ALGORITHM 只是弱签名算法问题的一类体现。与之齐名的还有 ERR_CERT_WEAK_KEY,通常是 RSA 密钥太短导致的,比如低于 2048 位;以及 ERR_SSL_WEAK_EPHEMERAL_DH_KEY,是 TLS 握手时临时 DH 密钥太短引起的。这些都是同一个大主题下的兄弟问题——浏览器在逐步淘汰不合规的加密算法和参数。
我之前还遇到过一种情况:证书用的是 SHA-256 签名,但服务器 TLS 配置里的 cipher suite 还残留着老旧的 RC4 或 DES 算法,Chrome 的报错信息就变成了“该网站使用了不受支持的协议”或者直接握手失败。所以排查 WEAK_SIGNATURE_ALGORITHM 的时候,一定要顺带检查服务器整体的 TLS 配置,否则修完算法问题,紧接着又冒出别的拦路虎。
3. 手工修复:用 OpenSSL 重新生成证书
3.1 方案选型:先判断你手里的证书是什么类型
要修复弱签名算法,最直接的办法就是让 CA 重新签发一张使用 SHA-256(或更强)签名的证书。但在动手之前,先分清楚你的证书是哪一类,因为处理路径完全不同:
- 商业 CA 签发的公网证书:比如你从 DigiCert、GlobalSign、GoDaddy、阿里云、腾讯云等购买的证书。这种情况不需要自己生成,直接去证书管理控制台申请重新签发即可。
- Let's Encrypt 免费证书:这种证书本来就是 SHA-256 签名,如果它还报错,多半是旧证书没更新干净或证书链不完整,重新执行一次签发脚本就行。
- 内部系统用的自签名证书:这个稍微麻烦一点,你需要自己用 OpenSSL 生成新的私钥和证书,再分发到各个客户端信任。
- 内部 CA 签发的证书:你需要更新 CA 的根证书策略,确保证书签名时指定的哈希算法是 SHA-256,然后重新签发。
无论是哪一类,底层核心操作都离不开 OpenSSL 这个工具。所以我先带你把 OpenSSL 手工处理整条链路走通。
3.2 检查当前私钥与证书的参数
不要直接闭着眼睛重新生成。先记录一下当前私钥和证书的信息,尤其是公钥长度、签名算法、序列号、有效期,这些信息在后续比对时会用到。
bash复制# 查看私钥信息
openssl rsa -in yourdomain.key -text -noout | grep -E "Private-Key|Public-Key"
# 查看证书完整信息
openssl x509 -in yourdomain.crt -noout -text | grep -E "Signature Algorithm|Public-Key|Not Before|Not After"
# 查看证书链
openssl crl2pkcs7 -nocrl -certfile yourdomain_fullchain.crt | openssl pkcs7 -print_certs -noout
拿到的信息里,Private-Key: (2048 bit) 代表私钥是 2048 位,这是最低安全要求了,建议直接上 4096 位。Signature Algorithm: sha256WithRSAEncryption 是理想状态。如果看到 sha1WithRSAEncryption,那问题就坐实了。
这里有个细节容易踩坑:如果你沿用之前的私钥重新提交 CSR,那么只要 CA 那边签发时指定的签名算法不强制是 SHA-1,通常结果就是 SHA-256。但为了保险起见,我建议直接重新生成私钥,一并把密钥强度升级到 4096 位。这样既解决了签名算法问题,又顺手提升了整体安全性。
注意:重新生成私钥会导致 SSL 会话重新协商,客户端需要重新握手,但影响很小,不需要担心。唯独要注意私钥备份问题——旧私钥如果丢了,可能导致部分移动端 App 的证书锁定机制报警。
3.3 生成新私钥与 CSR
执行下面这组命令,生成高强度的 RSA 私钥和 CSR:
bash复制# 生成 4096 位 RSA 私钥
openssl genrsa -out yourdomain_new.key 4096
# 基于私钥生成 CSR
openssl req -new -key yourdomain_new.key -out yourdomain_new.csr
生成 CSR 的过程中会交互式地询问国家、省份、城市、组织名称、通用名(Common Name)等字段。Common Name 一定要填写你的域名,而且最好是带 www 和不带 www 都做进 SAN(主题备用名称),这样浏览器才不会因为域名不匹配报错。
如果你有多个域名或子域名,建议写一个 openssl 配置文件一步到位。比如建一个 san.cnf 文件:
ini复制[req]
distinguished_name = dn
req_extensions = ext
[dn]
CN = www.example.com
[ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
DNS.3 = m.example.com
然后执行:
bash复制openssl req -new -key yourdomain_new.key -out yourdomain_new.csr -config san.cnf
这样生成的 CSR 会自动带上 SAN 扩展,后续浏览器校验域名时就不会有争议。
3.4 提交 CSR 并设置签名算法
拿到 CSR 之后,是找 CA 签还是自签,分两种情况。
对于商业证书,直接把 CSR 内容复制到证书管理后台的“重新签发”或“申请新证书”入口。在填写申请信息时,一般会有“签名算法”或“密钥算法”选项,有的面板默认就是 SHA-256,有的需要手动选一下。选择时优先选 SHA-256 with RSA,如果没有该选项,也至少选 SHA-384 或更高。注意不要选 SHA-1。
对于自签名证书,直接用 OpenSSL 一次性生成私钥 + 证书,并指定 SHA-256:
bash复制openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout server.key -out server.crt -days 825 -subj "/CN=myserver.local" -addext "subjectAltName=DNS:myserver.local,DNS:*.myserver.local"
这里的 -sha256 就指定了证书的签名算法,-days 825 是有效期,825 天约等于 Chrome 对公网证书的最大允许时长。-addext 是 OpenSSL 1.1.1 以上版本支持的写法,可以携带 SAN 扩展,很关键。
如果用的是旧版本 OpenSSL,-addext 可能不支持,那就还是走配置文件的方式,在配置文件里加上 subjectAltName 即可。
3.5 替换服务器证书并验证
证书签发完成后,把服务器配置里的证书路径指到新文件。以 Nginx 为例:
nginx复制server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/yourdomain_new_fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain_new.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
}
配置文件里有两个细节值得注意。第一,ssl_certificate 指向的文件最好是“证书链文件”(fullchain),也就是包含了你站点证书和中间证书的合并文件,而不是只放站点证书。如果只放站点证书,客户端会因为找不到中间证书而报 ERR_CERT_AUTHORITY_INVALID,虽然不会报弱签名错误,但同样打不开。
第二,ssl_protocols 和 ssl_ciphers 要同步更新。就算签名算法换成 SHA-256 了,如果你的 cipher suite 里还允许 RC4、3DES、SHA-1 这类老算法,Chrome 下一步就会给你 ERR_SSL_WEAK_CIPHER_SUITE。我建议直接用上面给出的那组 GCM cipher,顺便把 TLS 1.0/1.1 关掉,别再给老设备留后门了。
改完配置后,重载服务:
bash复制nginx -t && nginx -s reload
# 或者 Apache
apachectl configtest && systemctl reload httpd
重载后别急着开浏览器,先在服务器上自测一下:
bash复制openssl s_client -connect www.example.com:443 -servername www.example.com -tls1_3 2>/dev/null | grep "Verify return code"
openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -text | grep "Signature Algorithm"
第一行确认证书链校验结果,理想输出是 Verify return code: 0 (ok)。第二行确认叶子证书的签名算法,理想输出是 Signature Algorithm: sha256WithRSAEncryption。两个都通过,再去浏览器刷新,报错应该就消失了。
4. 自动化与更省事的替换方案
4.1 用 Let's Encrypt 十分钟完成替换
如果你的站点本来就在用 Let's Encrypt 的免费证书,那修复过程会非常快。Let's Encrypt 从 2016 年之后签发的证书默认就是 SHA-256,所以只要你的老证书还挂在服务器上,重新执行一次证书签发和部署就完事了。
用 certbot 的话,一条命令搞定:
bash复制# 先更新 certbot 到最新版
sudo apt update && sudo apt install -y --only-upgrade certbot
# 自动检测 Nginx 配置并签发替换
sudo certbot --nginx -d www.example.com -d example.com --key-type rsa --rsa-key-size 4096
certbot 会自动生成新私钥和 CSR,申请证书,然后修改 Nginx 配置。完成后它还会发邮件提醒你续期时间。我建议同时加个自动续期任务:
bash复制# 测试续期流程是否正常
sudo certbot renew --dry-run
# 配置 cron 每天执行两次续期检查
echo "0 3 * * * /usr/bin/certbot renew --quiet" | sudo tee -a /etc/crontab
如果你用的是 acme.sh 或其他 ACME 客户端,原理类似:删除旧的证书目录,重新申请,然后 reload 服务。这里要留意一点:如果你之前用 acme.sh 注册账号时指定了 --key-length 2048,新证书的私钥还是 2048 位。虽然签名算法与私钥长度是两个维度,但为了长远安全,建议把 --key-length 改为 4096 重新注册一次。
4.2 内部系统与自签名证书的特殊处理
内网系统和个人自建服务往往没有条件购买商业证书,也走不了 ACME 自动签发,这时自签名证书就成了唯一选择。但自签名证书面临的局面是“没有权威第三方做信用背书”,所以需要把根证书导入到每台客户端的信任库里,才能在浏览器里走通。
我处理的内部系统场景大致分三类,处理套路各有差异:
- 单一服务:直接在服务端给该服务生成一张自签名证书,然后把证书导入客户端信任库。
- 多个服务:自建一个内部 CA,用这个 CA 给各个服务签证书,客户端只信任这个内部 CA 根证书,后续新增服务就不用反复去改客户端信任库。
- 已有内部 CA 但用的 SHA-1:需要先更新内部 CA 本身的签发策略,确保证书签名或 CRL 签名时不用 SHA-1,然后再重新签发所有子证书。
自建内部 CA 的命令大致如下:
bash复制# 1. 生成 CA 根私钥和根证书(注意签名算法为 SHA-256)
openssl genrsa -out ca.key 4096
openssl req -x509 -new -key ca.key -sha256 -days 3650 -subj "/CN=Internal CA" -out ca.crt
# 2. 为某个服务签发证书(上面 3.4 节已描述)
openssl req -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj "/CN=myserver.local"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 825 -sha256 -extfile san.cnf
-extfile san.cnf 这个参数很关键,不指定 SAN 的话,Chrome 可能因为“缺少 subjectAltName”直接拦截,那又是一个坑。
内部系统处理时最大的难点不是技术,而是“人”。很多老系统上线时配了证书锁定(Certificate Pinning),把旧证书的指纹硬编码在客户端代码里。如果你重新签发了证书,旧的指纹对不上,App 或代理层会直接拒绝连接。这种问题排查起来最累——你查服务器一切正常,但客户端一直连不上。遇到这种情况,先翻一下客户端有没有做 pinning,如果是,就需要同步更新代码里的证书指纹。
4.3 给服务器做一次“全面体检”
替换完证书只是第一步。既然是为了安全升级而动这个配置,我建议顺手把服务器的 TLS 整体配置都过一遍,一劳永逸。
可以用网上免费的在线扫描工具 SSL Labs,也可以本地跑 testssl.sh 这个脚本,两者都能给出从 A+ 到 F 的评分,并列出所有检测到的问题。testssl.sh 的使用方式非常直接:
bash复制git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh --color 0 www.example.com
跑完重点看这几项:
- 证书签名算法是否已是 SHA-256+;如果不是,报错。
- 是否有 SHA-1 签名的中间证书;这种情况证书链里混着旧证书,需要把中间证书替换成新签发的。
- RSA 密钥位数是否 ≥ 2048;如果还是 1024,浏览器迟早给你
ERR_CERT_WEAK_KEY。 - TLS 协议版本是否支持 1.2 和 1.3;如果只支持 1.0 或 1.1,建议尽快升级服务器软件版本。
- 加密套件里是否含有 CBC、RC4、3DES 等弱算法;用 TCM cipher 或其他 GCM 套件替换。
做完这一整套检查,基本可以确定弱算法的问题被彻底清理干净了。
5. 常见问题与排查技巧实录
5.1 高危问题速查表
我一直觉得,技术博客最有价值的部分往往不是主流程,而是那些“按教程做完还是不行”的边边角角。我把这几年遇到的相关问题整理成一张速查表,你先过一遍:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
换新证书后仍报 WEAK_SIGNATURE_ALGORITHM |
证书链中还残留旧的 SHA-1 中间证书 | 把中间证书替换为与叶子证书配套的新证书,重新合并 fullchain |
| 浏览器报错,但 openssl 自测正常 | 客户端或代理缓存了旧证书链 | 清理浏览器缓存或系统根证书库,重启代理服务 |
证书签名算法已是 SHA-256,但仍报 ERR_CERT_WEAK_KEY |
RSA 私钥长度不足 2048 位 | 重新生成 4096 位私钥并重新签发证书 |
| 内网系统换证书后 App 连接失败 | 客户端有证书锁定,硬编码了旧指纹 | 定位并更新证书指纹,或临时关闭 pinning 验证 |
自签名证书在 Chrome 里报 ERR_CERT_AUTHORITY_INVALID |
根证书未导入客户端信任库,或没有 SAN 字段 | 导出根证书并导入系统信任库;确保证书带 SAN 扩展 |
| Let's Encrypt 续期后报错 | 证书路径未指向最新文件,或未重载服务 | 检查 Nginx/Apache 证书路径,重启或 reload 服务 |
| 修改 Nginx 后配置测试失败 | 证书/私钥不匹配 | 比对证书和私钥的公钥指纹,确保是同一对 |
5.2 三个值得说说的实操心得
第一个心得是:排查证书问题,永远先从证书链看起,而不是只看叶子证书。
有次客户报障,说换了新证书仍报 WEAK_SIGNATURE_ALGORITHM。我拿到 fullchain 文件一看,里面共三段证书:第一段是新的叶子证书,SHA-256 签名;第二、三段是老中间证书,SHA-1 签名。问题就是当初拼接 fullchain 时,直接把旧的中间证书带进去了。这种情况单独看叶子证书的签名算法完全没有问题,但浏览器检查的是叶子证书 + 中间证书的整个链路,只要某一环不是 SHA-2 或更高,都会拉响警报。所以排查时最好把每级证书都过一遍:
bash复制openssl crl2pkcs7 -nocrl -certfile yourdomain_fullchain.crt | \
openssl pkcs7 -print_certs -noout -text | \
grep -E "Subject:|Signature Algorithm"
第二个心得是:不要以为免费的证书就低人一等。 Let's Encrypt 的证书和商业证书在签名强度上完全一致,都是 SHA-256 + RSA 2048/4096,浏览器不会因为你是免费证书就额外给脸色看。很多“免费证书导致浏览器报错”的说法其实是把证书链没配好、ACME 续期断掉、或系统时间不对导致证书时间校验失败,这几个问题误记到了免费证书头上。如果你的服务器上本来就有 ACME 客户端,直接用上面的办法重新签发,往往比去面板申请商业证书还快。
第三个心得是:系统和浏览器的时间必须正确。 证书的校验依赖绝对时间。如果你服务器系统时间快了或慢了几分钟,即使签名算法合规、证书链完整,浏览器也可能报 ERR_CERT_DATE_INVALID 或其他莫名奇妙的错误。我排查过不少“证书换了还是打不开”的案例,最后发现是服务器时钟漂移导致的。顺手用 chronyc 或 ntpdate 同步一下时间基线,能省掉很多疑神疑鬼的时间。
5.3 老顽疾:“明明刚改过,还是报错”怎么破
这种情况十有八九是缓存和旧进程在捣乱。具体排查顺序我建议按下面来:
- 强制刷新浏览器。Chrome 里按
Ctrl+Shift+R(Windows)或Cmd+Shift+R(Mac),跳过缓存重新加载页面。 - 用隐身模式打开页面,因为隐身模式默认不带缓存,可以直接排除浏览器缓存干扰。
- 在局域网或另一台设备上访问同域名。如果其他设备正常,说明是当前设备本地缓存了旧证书链。
- 查看服务器端进程是否真的已经重载了新证书。Nginx 有时 reload 后 worker 进程还持有旧证书句柄,需要先
nginx -t再 reload,必要时直接systemctl restart nginx强制重启。 - 检查是否有 CDN 或反代层。如果网站走的是 Cloudflare、阿里云 CDN、Nginx 反代等,客户端看到的是 CDN 节点的证书,而不是源站的证书。你要在 CDN 控制台也把证书替换成新的,才能彻底解决。
最后这种情况才是最隐蔽的。很多源站换了新证书,但因为 CDN 节点还持有旧证书,浏览器看到的依然是 SHA-1 签名。排查时可以用 openssl s_client 直接连接域名,输出的证书 Subject 和 Signature Algorithm 如果和你源站配置的不一致,那就说明中间有一层代理或 CDN 改了证书,需要去对应控制台更新。
根据我个人经验,弱签名算法这类问题最怕的就是“没有全局视角”。修证书只看叶子证书,排查错误只盯服务器端,最后往往白忙一场。把证书链、客户端缓存、中间代理这三层都过一遍,基本上五分钟内就能定位根因。
这个小技巧我一直很受用:排查 SSL 问题时,先在服务器本机上用 openssl 查一遍证书链,再在浏览器里打开开发者工具 → Security 面板看一遍浏览器视角下的证书状态。两边一对比,问题在哪一层立见分晓。这套方法对 WEAK_SIGNATURE_ALGORITHM、证书过期、链不完整、域名不匹配都适用,值得收藏一下。
