Python requests库使用数字证书时无法完成SSL连接问题求助
问题原因排查与解决方案
首先明确两个报错的本质:
[SSL: CERTIFICATE_VERIFY_FAILED]是本地客户端校验服务器侧的证书不通过- 加
verify=False后出现的[SSL: SSLV3_ALERT_BAD_CERTIFICATE]是服务器侧校验你提交的客户端证书不通过,此时已经绕过了本地对服务器证书的校验,问题出在客户端证书本身、提交格式或者服务端的校验规则上。
你可以按以下步骤逐一排查:
1. 校验客户端证书和密钥的匹配性与有效性
- 首先确认证书与私钥是否配对,执行以下两条命令,输出的MD5值必须完全一致:
openssl x509 -noout -modulus -in /path/to/cert.crt | openssl md5 openssl rsa -noout -modulus -in /path/to/cert.open.key | openssl md5 - 确认私钥没有设置密码保护,requests原生不支持传带密码的私钥,若有密码需要先解密后再使用。
- 确认客户端证书在有效期内,且当前目标服务的信任根CA列表包含该客户端证书的签发机构。
2. 检查证书文件格式
- 确认你使用的
.crt文件为PEM格式,文件开头应为-----BEGIN CERTIFICATE-----,如果是二进制DER格式,需要先转换:openssl x509 -inform der -in 原证书路径.der -out 输出路径.pem - 部分服务要求客户端证书需附带完整的证书链,你可以把客户端证书、对应的中间证书、根证书按顺序拼接在同一个PEM文件中,再替换原来的
.crt文件测试。
3. 排除环境与配置干扰
- 先去掉代理参数直连服务测试,避免代理篡改SSL握手报文或者要求额外的证书配置。
- 确认目标服务支持的TLS版本,部分老旧服务仅支持低版本TLS协议,你可以通过自定义Adapter强制指定协议版本测试:
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager import ssl # 示例指定TLS 1.2,可根据服务实际支持的版本替换为ssl.PROTOCOL_TLSv1_1等 class CustomTLSAdapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=False, **pool_kwargs): self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, ssl_version=ssl.PROTOCOL_TLSv1_2, **pool_kwargs ) session = requests.Session() session.mount("https://", CustomTLSAdapter()) response = session.get( url_server, cert=("/path/to/cert.crt", "/path/to/cert.open.key"), headers=headers, verify="/path/to/你的CA根证书bundle文件" )
4. 用openssl工具获取详细报错信息
你可以直接用openssl发起SSL握手,得到更详细的错误定位:
openssl s_client -connect 你的服务域名:端口 -cert /path/to/cert.crt -key /path/to/cert.open.key -CAfile /path/to/CA_bundle文件
根据输出的握手日志即可定位具体是哪一步校验失败。
内容的提问来源于stack exchange,提问作者Victor Cardel
相关产品推荐
相关产品推荐

