Python requests/urllib3验证自签名证书时出现主机名不匹配错误
问题原因及解决方法
可能的原因
- 证书缺少SAN字段:Python的SSL验证(依赖urllib3)在新版本中优先校验Subject Alternative Name(SAN)字段,而非传统的CN字段。即便CN与域名匹配,若证书未添加对应域名的SAN条目,就会触发主机名不匹配错误。Firefox和部分openssl版本会回退使用CN验证,因此能正常通过。
- Python版本兼容问题:旧版Python(如3.6及更早)的ssl模块对自签名证书的SAN处理存在局限,或证书格式校验更严苛。
- 系统证书存储冲突:Python可能加载了系统默认证书存储中的冲突证书,干扰了自签名证书的验证逻辑。
解决方法
补全证书的SAN字段(推荐生产环境使用)
重新生成包含SAN字段的自签名证书:
- 创建openssl配置文件(例如
openssl.cnf):[req] distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [req_distinguished_name] CN = selfsigned.xython.fr [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = selfsigned.xython.fr - 执行openssl命令生成证书和密钥:
openssl req -x509 -newkey rsa:4096 -nodes -keyout server.key -out server.crt -days 365 -config openssl.cnf
临时关闭证书验证(仅测试环境)
如果仅用于测试,可临时禁用验证,但生产环境绝对禁止:
import requests import urllib3 # 屏蔽不安全请求警告 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # 跳过证书验证 response = requests.get('https://selfsigned.xython.fr', verify=False)
指定自签名证书路径验证
让requests使用你的自签名证书完成验证:
import requests # 传入自签名证书文件路径 response = requests.get('https://selfsigned.xython.fr', verify='/path/to/your/server.crt')
升级Python版本
若使用旧版Python,升级至3.7及以上版本,新版本的ssl模块对SAN字段的处理更符合标准,兼容性更佳。
内容的提问来源于stack exchange,提问作者montjoie
相关产品推荐
相关产品推荐

