HTTPS配置老出错?最常见的几个坑和解法

HTTPS现在基本是标配,但配起来出错的情况真的不少。很多错误看起来各不相同,其实原因就那几类,摸清楚了基本不会被绕晕。

证书不受信任 / NET::ERR_CERT_AUTHORITY_INVALID

这个报错最常见的原因是证书链不完整。SSL证书分为根证书、中间证书和叶证书,浏览器需要能从你的证书一路验证到它信任的根证书。如果中间证书没有正确配置,浏览器就会报错。

解决方法:去证书提供商那里下载完整的证书链文件(通常是fullchain.pem或者包含中间证书的bundle.crt),配置Nginx或Apache时要用完整链文件,不要只用叶证书。

# Nginx正确配置示例
ssl_certificate /etc/ssl/certs/fullchain.pem;   # 完整链
ssl_certificate_key /etc/ssl/private/privkey.pem;

用Let’s Encrypt的话,certbot会自动生成完整链,不存在这个问题。

证书和域名不匹配

申请证书时填写的域名要和实际访问的域名完全一致。

  • example.comwww.example.com是两个不同的域名,申请时要确认包含两者,或者申请通配符证书*.example.com
  • 子域名也要单独申请,或者申请SAN证书把多个域名写进去

用certbot申请时可以-d参数指定多个域名:

certbot --nginx -d example.com -d www.example.com

HTTP和HTTPS混合内容警告(Mixed Content)

站点改成HTTPS后,如果页面里还有图片、JS、CSS是通过HTTP加载的,浏览器会报Mixed Content警告,严重的会直接阻止加载。

WordPress用户可以安装Really Simple SSL插件,会自动把绝大多数HTTP资源替换成HTTPS。

也可以在wp-config.php里加:

define('FORCE_SSL_ADMIN', true);

然后检查数据库里有没有硬编码的HTTP链接,用插件”Better Search Replace”全局替换一遍。

证书已过期

Let’s Encrypt证书每90天过期一次,如果没有设置自动续期会出问题。

# 检查自动续期定时任务
crontab -l | grep certbot

# 手动测试续期(不会真正续期)
certbot renew --dry-run

建议同时在证书到期前一周设置监控告警,推荐用UptimeRobot,免费版就能监控SSL证书到期时间。

HSTS导致无法访问

这个坑比较隐蔽。如果之前开启了HSTS(HTTP Strict Transport Security),浏览器会强制用HTTPS访问你的域名,并把这个记录缓存下来。

如果后来证书出了问题或者你想临时改回HTTP,浏览器会拒绝访问,报ERR_SSL_PROTOCOL_ERROR,清缓存也没用。

解决方法:在Chrome地址栏输入chrome://net-internals/#hsts,找到你的域名,点Delete,清除HSTS记录。

如果是Nginx配置了HSTS响应头:

add_header Strict-Transport-Security "max-age=31536000" always;

先把max-age改成0,等待缓存过期后再处理其他问题。

快速自查工具

遇到HTTPS问题先去 SSL Labs 跑一遍,它会给出详细的证书链、配置问题和评级,大部分问题在报告里都能找到线索。