Python Requests使用自定义SSL证书时证书验证失败求助
解决requests自定义SSL证书验证失败问题
核心问题分析
你遇到的CERTIFICATE_VERIFY_FAILED错误,核心原因大概率是你提供给verify参数的是服务器证书,而非CA信任链证书。requests的verify参数要求传入的是签发目标服务器证书的CA根证书(或包含完整信任链的CA_BUNDLE文件),而浏览器地址栏下载的通常是服务器本身的证书,不是CA根证书。
具体排查与解决方案
1. 确认证书类型与信任链
先通过openssl命令检查证书的签发信息:
openssl x509 -in your_cert.pem -text -noout
- 如果是自签证书:
Issuer和Subject字段内容完全一致,此时服务器证书本身可作为CA证书使用,只需确保格式正确。 - 如果是第三方CA签发:需要获取该CA的根证书(可能还需中间证书),将所有证书拼接成PEM格式的CA_BUNDLE。
2. 优化证书加载方式(无需临时文件)
避免临时文件的潜在问题,直接通过SSLContext加载证书内容,更高效可靠:
import ssl import requests import base64 from cryptography.x509 import load_der_x509_certificate from cryptography.hazmat.primitives import serialization def execute_get_request_with_custom_certificate(self, url: str, headers: dict): cert = get_certificate_from_db() decoded_cert = base64.b64decode(cert) # 处理DER格式证书(浏览器下载可能是DER),转为PEM格式 try: # 尝试直接解析为PEM pem_cert = decoded_cert.decode('utf-8') ssl_context = ssl.create_default_context(cafile=None) ssl_context.load_verify_locations(cadata=pem_cert) except UnicodeDecodeError: # 解析为DER格式,转换为PEM cert_obj = load_der_x509_certificate(decoded_cert) pem_cert = cert_obj.public_bytes(encoding=serialization.Encoding.PEM).decode('utf-8') ssl_context = ssl.create_default_context(cafile=None) ssl_context.load_verify_locations(cadata=pem_cert) return requests.get(url, headers=headers, verify=ssl_context)
3. 额外检查点
- 域名匹配:确认证书的
Subject Alternative Name(SAN)字段包含你请求的域名,或Common Name(CN)与域名一致。 - 证书有效期:检查证书的
Not Before和Not After字段,确认证书未过期。 - 权限问题:临时文件在某些系统下可能存在权限限制,导致
requests无法读取(不过你用flush()已确保写入完成,此概率较低)。
内容的提问来源于stack exchange,提问作者LukaUr
相关产品推荐
相关产品推荐

