Chrome访问站点SSL证书正常但requests报证书验证失败如何排查
开启详细SSL错误日志的方法
方法1:启用urllib3调试日志
requests底层依赖urllib3实现TLS握手,开启urllib3的debug日志可输出完整的握手交互、证书校验全流程信息:
import logging import requests # 全局开启DEBUG级日志 logging.basicConfig(level=logging.DEBUG) # 强制urllib3输出详细请求日志 urllib3_log = logging.getLogger("urllib3") urllib3_log.setLevel(logging.DEBUG) urllib3_log.propagate = True requests.get("https://somerandomsite.subdomain.com")
日志会明确标注证书校验失败的具体环节,比如根证书缺失、证书有效期错误、域名不匹配等。
方法2:使用openssl工具直接校验证书链
无需编写代码,直接执行命令即可输出完整的证书链与校验结果:openssl s_client -connect somerandomsite.subdomain.com:443 -servername somerandomsite.subdomain.com -showcerts
重点查看输出末尾的Verify return code字段,会直接返回校验失败的错误代码与说明。
方法3:校验CA根证书列表
requests默认使用certifi库提供的根证书集合,可通过以下代码确认证书文件路径,手动检查是否包含Google R3根证书:
import certifi print(certifi.where())
打开输出路径对应的pem文件,搜索Google R3关键词即可确认根证是否存在。
常见问题诱因分析
- 服务端证书链配置缺失:Chrome会自动补全缺失的中间证书,而requests要求服务端返回完整的证书链(叶证书+Google R3中间证书),如果服务端仅返回叶证书,会直接触发校验失败,这是Let's Encrypt证书最常见的配置问题。
- certifi库版本过旧:低版本的certifi没有收录Google R3根证书,执行
pip install --upgrade certifi更新根证书集合即可解决。 - HTTPS中间人劫持:如果网络环境存在代理、防火墙对HTTPS流量做了中间人替换,插入的自签名证书可能已经被系统根证书信任(Chrome读取系统根证),但requests默认不读取系统根证书,就会触发校验失败。
- SNI兼容问题:如果服务端同一IP托管了多个HTTPS站点,低版本requests不支持SNI扩展会拿到错误站点的证书,升级requests到最新版本即可解决。
- 设备系统时间偏差:运行requests的设备系统时间如果不在证书的有效期范围内,也会触发校验失败。
内容的提问来源于stack exchange,提问作者Shaurya Chaudhuri
相关产品推荐
相关产品推荐

