SSL证书验证问题的背景
在使用Python的requests库进行HTTP PUT请求时,session.put()方法是常用的接口调用方式。然而,当目标服务器使用自签名证书或证书配置不当时,经常会遇到SSLError或CertificateError等SSL验证异常。这类问题在内部系统、测试环境或某些CDN场景中尤为常见。
问题现象与错误分析
典型的SSL证书验证错误表现为:
requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: /api/resource (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))
这种错误的核心原因是requests库默认启用了严格的SSL证书验证机制。当遇到以下情况时就会触发错误:
- 自签名证书
- 证书链不完整
- 证书域名不匹配
- 证书已过期
- 系统缺少根证书
解决方案与代码示例
1. 禁用证书验证(不推荐用于生产环境)
最简单的解决方式是关闭SSL验证,但这会降低安全性:
import requests
session = requests.Session()
response = session.put('https://example.com/api',
data={'key': 'value'},
verify=False)
2. 指定自定义CA证书包
更安全的做法是提供自定义CA证书:
session.put('https://example.com/api',
data={'key': 'value'},
verify='/path/to/certfile.pem')
3. 修改全局验证设置
可以为整个session设置验证参数:
session.verify = '/path/to/certfile.pem'
response = session.put('https://example.com/api', data={'key': 'value'})
4. 使用环境变量指定证书
通过设置环境变量指定证书路径:
import os os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/certfile.pem'
最佳实践建议
1. 开发环境:可以使用verify=False快速测试,但务必在提交代码前移除
2. 生产环境:应该配置正确的CA证书包,推荐使用系统信任链或官方CA包
3. 证书管理:定期更新证书,确保证书链完整且未过期
4. 错误处理:建议封装请求方法,加入适当的异常捕获和重试机制
高级配置选项
对于更复杂的需求,requests还支持:
- 客户端证书认证(
cert参数) - SSL版本控制
- 密码套件配置
- 证书吊销检查
这些高级配置需要通过urllib3底层实现,通常需要创建自定义的HTTPAdapter。