很多开发者在为小程序后端服务配置 HTTPS 时,明明已经上传了 SSL 证书,却在浏览器或小程序开发者工具中看到“证书不受信任”的警告。这类问题不仅影响调试效率,还可能直接导致小程序请求被拦截。下面我们从原理出发,一步步排查并解决这个问题。
为什么会出现“证书不受信任”的提示?
浏览器或客户端判断一个 HTTPS 证书是否可信,依赖于完整的信任链验证。如果中间任何一个环节缺失或配置错误,就会触发安全警告。常见原因包括:
- 证书链不完整:只部署了站点证书,未包含中间 CA 证书。
- 使用了自签名证书:未由受信任的证书颁发机构(CA)签发。
- 域名不匹配:证书绑定的域名与实际访问的域名不一致(如证书为
api.example.com,但访问的是www.api.example.com或 IP 地址)。 - 服务器时间错误:系统时间与证书有效期不匹配,导致浏览器认为证书“未生效”或“已过期”。
- 证书格式或拼接错误:证书文件包含 BOM 头、缺少换行符,或私钥与公钥不匹配。
第一步:确认证书来源与类型
首先,确保你使用的 SSL 证书来自受信任的 CA 机构(如 Let’s Encrypt、DigiCert、Sectigo 等)。自签名证书仅适用于本地测试,无法通过小程序或现代浏览器的安全校验。
- 登录你申请证书的平台,下载完整的证书包,通常包含:
- 站点证书(如
your_domain.crt) - 中间证书(如
intermediate.crt) - 私钥文件(如
your_domain.key)
- 站点证书(如
- 不要使用仅包含站点证书的文件,必须拼接完整的证书链。
第二步:正确拼接证书链
Nginx 要求 ssl_certificate 指向一个包含完整信任链的 PEM 文件。拼接顺序为:站点证书在上,中间证书在下。
- 在 Linux 或 macOS 终端执行以下命令拼接证书(Windows 用户可用记事本操作):
cat your_domain.crt intermediate.crt > fullchain.pem - 确保文件内容格式正确,每段证书以
-----BEGIN CERTIFICATE-----开头,以-----END CERTIFICATE-----结尾,中间无多余空行或特殊字符。 - 验证私钥与证书是否匹配:
openssl x509 -noout -modulus -in fullchain.pem | openssl md5 openssl rsa -noout -modulus -in your_domain.key | openssl md5两个命令输出的 MD5 值必须一致。
第三步:配置 Nginx
在 Nginx 配置文件中正确引用证书和私钥:
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/your_domain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE+AESGCM:DHE+AESGCM:AES256+EECDH:AES256+EDH;
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意:如果同一服务器部署多个 HTTPS 站点,只能有一个 listen 443 ssl default_server;,其余站点不得重复使用 default_server,否则 Nginx 启动会报错。
第四步:验证部署效果
配置完成后,执行以下步骤验证:
- 测试 Nginx 配置是否合法:
nginx -t - 重载配置:
nginx -s reload - 使用在线工具检查证书链完整性,例如:
- SSL Labs 的 SSL Test(
https://www.ssllabs.com/ssltest/) - SSL Checker(
https://www.sslshopper.com/ssl-checker.)
- SSL Labs 的 SSL Test(
- 在手机端(尤其是 iOS 和 Android)用浏览器访问,确认无警告。小程序环境对证书要求更严格,建议在真机调试。
第五步:排查混合内容与域名一致性
即使证书本身没问题,以下情况也会导致“不安全”提示:
- 混合内容(Mixed Content):网页或 API 响应中引用了 HTTP 资源(如图片、JS、CSS)。小程序会直接拦截此类请求。解决方案:确保所有资源使用 HTTPS 或相对协议(
//example.com/resource.js)。 - 访问域名与证书不一致:证书必须覆盖你实际使用的域名。如果使用泛域名证书(如
.yourdomain.com),注意它不包含根域名(yourdomain.com),需单独申请或使用多域名(SAN)证书。
常见误区与避坑指南
| 误区 | 正确做法 |
|---|---|
| 只上传站点证书,忽略中间 CA | 必须拼接完整证书链(站点 + 中间 CA) |
| 用 Windows 记事本编辑 PEM 文件导致 BOM 头 | 使用 VS Code、Notepad++ 或命令行编辑,保存为 UTF-8 无 BOM 格式 |
| 在 Nginx 中配置多个 default_server on 443 | 仅保留一个 default_server,其余站点移除该参数 |
| 使用 IP 地址申请证书 | 公共 CA 通常不为 IP 颁发证书,应使用域名 |
常见问题 FAQ
| 问题 | 解答 |
|---|---|
| 为什么电脑浏览器正常,但手机或小程序报证书错误? | 部分旧设备或小程序环境缺少中间 CA 证书,必须部署完整证书链才能被信任。 |
| 能否用免费证书(如 Let’s Encrypt)用于小程序后端? | 可以,只要正确部署完整证书链,且域名匹配,Let’s Encrypt 证书被所有主流平台信任。 |
| 证书部署后仍提示“您的连接不是私密连接”怎么办? | 优先检查证书链是否完整、域名是否匹配、服务器时间是否准确,并使用 SSL Labs 工具验证。 |
| 多个子域名如何配置证书? | 可申请泛域名证书(.example.com)或 SAN 证书(多域名证书),确保覆盖所有访问的子域名。 |
| Nginx 重启后 HTTPS 无法访问? | 检查 443 端口是否开放,云服务器安全组是否放行 HTTPS 流量,并确认 Nginx 配置无语法错误。 |