如何使用Python requests库的session.raw方法解决SSL证书验证问题?

1. 问题背景

在使用Python的requests库进行HTTP请求时,session.raw方法因其底层原始响应处理能力备受开发者青睐。然而,当涉及HTTPS请求时,SSL证书验证问题成为高频痛点。典型错误包括:

  • SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]
  • requests.exceptions.SSLError异常
  • 自签名证书或过期证书导致的连接中断

2. 根本原因分析

SSL/TLS证书验证是HTTPS安全通信的核心环节。以下场景会触发验证失败:

  1. 证书链不完整:服务器未返回完整的中间证书
  2. 域名不匹配:证书Subject Alternative Name (SAN)与请求域名不符
  3. 系统CA存储缺失:Python无法定位系统的根证书库
# 示例错误代码  
import requests  
s = requests.Session()  
resp = s.get('https://expired.badssl.com', verify=True)  # 显式触发验证

3. 解决方案

3.1 临时禁用验证(仅限测试环境)

通过设置verify=False跳过验证,但会引发安全警告

resp = s.get('https://example.com', verify=False)  
# 需配合禁用警告  
import urllib3  
urllib3.disable_warnings()

3.2 指定自定义CA证书

使用verify参数指定PEM格式的证书文件:

resp = s.get('https://example.com', verify='/path/to/cert.pem')

3.3 修改Session默认配置

全局配置Session对象的验证策略:

s = requests.Session()  
s.verify = '/path/to/cert_bundle.crt'  # 或 False

4. 高级技巧

4.1 动态证书加载

结合certifi库扩展CA存储:

import certifi  
s.verify = certifi.where()  # 使用certifi的证书库

4.2 自定义验证逻辑

继承requests.adapters.HTTPAdapter实现自定义验证:

class CustomAdapter(requests.adapters.HTTPAdapter):  
    def cert_verify(self, conn, url, verify, cert):  
        super().cert_verify(conn, url, '/custom/path', cert)  

s.mount('https://', CustomAdapter())

5. 生产环境最佳实践

  • 使用Let's Encrypt等免费CA签发有效证书
  • 定期检查证书有效期(推荐工具:openssl x509 -checkend
  • 在Docker中确保ca-certificates包已更新