解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示"errno":600001证书验证失败的问题

前言

微信小程序在生产环境必须使用域名发起HTTPS请求。
这就需要配置HTTPS。
通常我们的nginx配置文件可以很简单,只需要配置证书和私钥就行:

ssl_certificate your.server.domin.cer;
ssl_certificate_key your.server.domin.key;

此时,使用浏览器发起请求时,已经可以看到小锁了,类似这样:

解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

但使用微信小程序发起请求时,就可能遇到玄学问题:

  1. 在开发工具里可以正常发起请求
  2. 真机调试时,无法向后台发起请求,提示"errno":600001
  3. 由于手机型号和系统不同,甚至出现“有的手机可以访问但有的不行”的情况

本文来解决这个问题。

原因分析

先贴出完整的控制台信息:

{"errno":600001,"errMsg":"request:fail errcode:-202 cronet_error_code:-202 error_msg:net::ERR_CERT_AUTHORITY_INVALID"}

Screenshot_20230705_155958.png

简单翻译一下就是:证书验证失败。

这个时候就纳闷了:明明我浏览器已经提示安全了啊?怎么微信小程序就不行了呢?

去查这个600001错误代码,的确有其他人遇到过,比如这个问答:
https://developers.weixin.qq.com/community/develop/doc/000408...

但网上查不到非常有价值的信息,只是知道可能是“证书链”的问题,
官方文档对于HTTPS证书这一块有这些要求:

解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

其中有一条就是证书信任链必须完整。

那么怎么查呢?

这个网站 https://myssl.com/ 提供了证书检测的功能。

HTTPS是工作在应用层的,所以必须输入"协议+域名+端口"而不是"协议+域名"

对于一个小程序连不上的后台地址,会提示证书评级为B级,并且证书链不完整:
解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

确实是证书的问题。

那么怎么解决呢?

解决

对于通过acme自动化部署的证书,部署时会生成一组文件,包括:

  • ca.cer——颁发机构CA的证书
  • fullchain.cer——完整证书链
  • your.domin.cer——本级域名证书
  • your.domin.key——本级域名私钥

可能还有其他文件,但我们只需要研究这几个就可以了。

通常直觉上一看,your.domin.cer和your.domin.key这俩文件齐刷刷的,肯定就是这俩了。

这样确实可以,而且浏览器也认可这个证书,但是小程序不认。

证书链不完整的意思就是:只加载了本级域名的证书但没有加载CA的证书。这就是小程序不能用的直接原因。

另外,如果我们输出your.domin.cer、ca.cer、fullchain.cer,就会惊奇的发现,fullchain.cer就是前面两个文件内容连起来,看图:

ca.cer:
解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

domin.cer:
解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

fullchain.cer(注意看,这里是两段):
解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

所以,fullchain = ca + yourdomin

结论很简单,如果你部署证书的文件夹中有两段的fullchain.cer文件,就用这个文件作为证书;
如果某些证书发放机构没有给出完整的证书链,就把yourdomin和ca这两个文件拼起来作为证书。

这样一波操作之后,再检测一下证书,就是A级了:

解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示

此时小程序也可以访问正常。

总结

  1. 浏览器只需要有证书和私钥就能通过认证,但小程序多认证了一个证书链
  2. 完整的证书链包括本级域名的信息和CA的信息
  3. 如果nginx只加载本级域名证书,而没有CA的证书,就是证书链不完整,证书评级是B,就会出现“网页能访问但小程序提示不安全”的问题
  4. 解决方法就是使用完整的证书链,可以使用颁发机构生成的,也可以手动拼接

本文只发布segmentfault,禁止转载,如在其他平台看到请举报。

你可能感兴趣的:(解决nginx开启HTTPS之后,网页正常但微信小程序无法连接,提示"errno":600001证书验证失败的问题)