Python Requests库SSL证书问题排查求助(Python 3.7)
解决Requests代理访问HTTPS站点的SSL证书问题
咱们一步步拆解你遇到的问题,逐个解决:
1. 初始请求报SSL: CERTIFICATE_VERIFY_FAILED的原因
这个错误是因为你的代理服务器使用了自签名SSL证书,而requests默认会验证整个证书链的合法性——自签名证书不在系统信任的CA列表里,所以验证直接失败了。
2. 用verify=False返回403的问题
verify=False确实能跳过证书验证,但很多服务器(或者你的代理)会检测到这种不安全的请求,直接返回403禁止访问;另外也有可能是代理本身要求客户端提供合法证书才能通过代理。
3. 用cert参数报错的核心问题
你搞混了cert和verify两个参数的作用:
cert是用来指定客户端证书(当服务器要求客户端提供证书来验证身份时才用)verify才是用来指定信任的CA证书(让requests信任自签名证书的正确参数)
而且Chrome下载的site.cer是DER格式的证书,requests需要的是PEM格式,直接使用就会触发PEM lib错误。
正确的解决方案步骤:
步骤1:把DER格式证书转换成PEM格式
Chrome下载的.cer通常是DER编码,需要转换成PEM格式才能被requests识别:
- 如果你有openssl工具,直接用命令行转换:
openssl x509 -inform der -in site.cer -out site.pem
- 没有openssl的话,用Python代码转换也可以:
import ssl # 读取DER格式证书 with open('site.cer', 'rb') as der_file: der_data = der_file.read() # 转换为PEM格式 pem_data = ssl.DER_cert_to_PEM_cert(der_data) # 保存PEM文件 with open('site.pem', 'w') as pem_file: pem_file.write(pem_data)
步骤2:用verify参数指定信任的PEM证书
现在把转换好的PEM证书路径传给verify参数,同时保留代理配置:
import requests proxies = {"https":"https://user:pwd@host:port"} # 注意这里用verify指定证书路径,不是cert r = requests.get("https://URL", proxies=proxies, verify='C:\\site.pem') print(r.status_code)
额外情况:如果代理要求客户端证书
如果你的代理本身要求你提供客户端证书(不是信任代理的证书),那才需要用cert参数——通常需要同时提供证书和私钥文件,如果证书和私钥在同一个文件里直接传路径,分开的话传元组('cert.pem', 'key.pem')。但从你的报错来看,这个场景不适用,你主要是需要信任代理的自签名证书。
关闭InsecureRequestWarning(可选)
如果实在要临时用verify=False(不推荐生产环境),又不想看到警告,可以添加:
import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
但还是建议用指定CA证书的方式,安全性更高。
内容的提问来源于stack exchange,提问作者Sujin Sam Arul Raj
相关产品推荐
相关产品推荐

