浏览器提示「不安全」不等于证书没装好——按经验,九成以上是证书链不完整或页面混入了 HTTP 资源(混合内容)这两类问题。排查顺序建议固定为:先看浏览器报什么错 → 用 openssl 验证证书链 → 核对域名与有效期 → 查页面混合内容 → 最后查 CDN/回源与 TLS 协议配置,这样 10 分钟内基本能定位到根因。
浏览器提示「不安全」到底分几种情况?
结论:先分清是「证书错误」还是「连接不安全」,两者的排查路径完全不同。
点地址栏的锁形/警告图标看提示文案:出现 NET::ERR_CERT_AUTHORITY_INVALID、ERR_CERT_COMMON_NAME_INVALID、ERR_CERT_DATE_INVALID,属于证书本身的问题,重点查证书链、域名(SAN)、有效期;出现「此页面正尝试加载不安全的内容」「连接不安全」但没有红色证书报错,属于混合内容问题,证书其实生效了,只是页面里有 http:// 资源。
一个实用判断:Chrome 里按 F12 打开开发者工具,切到 Console 面板,能看到 Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure resource 这类明确提示,基本可以直奔第 4 节。
证书链不完整怎么验证和修复?
结论:这是「证书装对了但浏览器仍不信任」最常见的原因——只部署了域名证书,没带中间 CA 证书。
验证命令(把域名换成你的):
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts
看输出里的 Verify return code:0 (ok) 表示链完整;出现 21 (unable to verify the first certificate) 或 20 (unable to get local issuer certificate),说明服务端只发了叶子证书,缺中间证书。
修复方法:把「域名证书 + 中间证书」按顺序合并成 fullchain 文件再配置,顺序不能颠倒(服务器证书在上,中间证书在下,根证书一般不需要)。Nginx 配置:
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
改完执行 nginx -t && nginx -s reload,再用上面的 openssl 命令验证一次,Verify return code 回到 0 即修复。部分系统和浏览器有中间证书缓存,验证时建议用无痕窗口或换网络测试。
证书域名不匹配、过期、时间不对怎么查?
结论:证书必须覆盖用户实际访问的那个主机名,example.com 和 www.example.com 在证书里是两个不同的名字。
查证书覆盖的域名列表:
echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -dates -subject -ext subjectAltName
重点看 subjectAltName 里有没有你访问的完整域名,通配符证书 *.example.com 只匹配一级子域,a.b.example.com 不覆盖。同时看 notBefore / notAfter,过期就续签。
还有一种容易被忽略的情况:证书没过期,但服务器系统时间不对(比如从快照恢复的云主机时间停留在几个月前),TLS 握手会判定期失效。用 date 确认服务器时间,用 timedatectl 或 ntpdate 校时后重试。
混合内容(Mixed Content)怎么定位?
结论:HTTPS 页面里任何一张 http:// 图片、一个 http:// 脚本或样式,都会让浏览器标记为「不完全安全」。
快速扫描页面里的 http 引用:
curl -s https://www.example.com/ | grep -o 'http://[^"'\'' ]*' | sort -u
结果里如果出现 http:// 开头的 js、css、图片地址,就是元凶。修复方式有两条:一是把资源地址全部改成 https:// 或协议相对写法(更好的做法是直接写 // 或相对路径);二是在页面 head 里加 CSP 升级指令:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
注意这是兜底手段,根本解法还是改源码。数据库里存的老文章、老图片如果是绝对 http 地址,需要一条 SQL 批量替换。
另外,curl -I http://example.com 看是否 301 到 https,以及是否有资源从 80 端口回源,也是必须检查的一环。
CDN、反向代理、TLS 协议还有哪些坑?
结论:如果源站证书正常、浏览器仍报错,问题大概率在 CDN 节点或 TLS 协议版本上。
常见三类:一是 CDN 上只上传了域名证书没上传中间证书,或者证书到期后 CDN 侧未同步更新;二是 CDN 到源站走 HTTP 回源,用户侧看着是 HTTPS,实际链路没有加密,部分浏览器或安全策略会提示;三是服务器禁用了 TLS 1.2 及以上版本或只开了弱加密套件,老配置里保留 SSLv3、TLS 1.0 会被现代浏览器直接拒绝。
推荐的协议配置:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
排查完想确认整体评级,可以用 SSL Labs 的在线测试,评分到 A 及以上基本说明链、协议、套件都没问题。
最后提醒两个低成本但高频的误判:一是浏览器缓存了旧的证书状态,换无痕窗口或清理 HSTS 记录再试;二是访问的是公司内网或被企业代理/杀毒软件做了 SSL 中间人拦截,这类环境会固定报证书不受信任,换手机 4G 网络访问一次即可排除。
整篇看下来,排查 SSL「不安全」其实就是五步:读报错文案定位方向 → openssl 查链和有效期 → 核对 SAN 域名 → 扫页面 http 资源 → 查 CDN 回源与 TLS 版本。建议把这几条命令存成一个小脚本,每次换证书后跑一遍,比等用户来反馈效率高得多。在 GJ 站长论坛的运维交流里,证书链缺失和新手把 fullchain 写成单证书,是被问得最多的两类问题,直接照着上面的命令验证一遍通常就能自证。