Requests发送带client certificate的请求需用cert参数:传元组(证书路径,私钥路径)或单个.pem文件路径;若私钥加密,需加密码构成三元组;常与verify参数配合校验服务端证书。

Requests 发送带 client certificate 的请求怎么写?
直接用 cert 参数传证书路径就行,但必须同时提供私钥和证书(可以合并为一个 .pem 文件,也可以分开为 .crt + .key)。Requests 本身不校验证书格式是否合法,出错往往卡在底层 OpenSSL 加载失败。
最简可用写法:
import requests
response = requests.get(
"https://api.example.com/secure",
cert=("/path/to/client.crt", "/path/to/client.key")
)注意:cert 是元组,不是字符串;如果证书和私钥合并了,就只传一个字符串路径:
cert="/path/to/client.pem"
证书加载失败常见报错及原因
requests.exceptions.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca —— 这不是 client cert 问题,是服务端没信任你的 CA,或你漏了 verify 参数指向服务端证书链。
立即学习“Python免费学习笔记(深入)”;
OSError: Could not find the TLS certificate file —— 路径错、权限不足、或文件被其他进程占用(尤其 Windows 下编辑过 .pem 后没关闭编辑器)。
ssl.SSLError: PEM routines:PEM_read_bio_PrivateKey:bad password read —— 私钥有密码但没提供 cert 元组第三项(密码),Requests 不支持交互式输密,必须显式传入:
cert=("/path/to/cert.pem", "/path/to/key.pem", "mypassword")- 密码错误或为空字符串时也会报这个错
cert 和 verify 参数能不能混用?
能,而且经常要一起用。client cert 解决“你是谁”,verify 解决“我信不信你连的服务器”。默认 verify=True 会校验服务端证书(走系统 CA),但内网或自签场景下必须指定 CA bundle:
-
verify="/path/to/ca-bundle.crt"—— 指向可信根证书文件 -
verify=False—— 禁用校验(开发调试可用,生产禁用) - 如果服务端证书由你签发的 CA 颁发,
verify必须指向该 CA 的 root.crt,否则握手直接失败
典型组合:
requests.get(
"https://internal-api.company.local",
cert=("/etc/ssl/client.pem", "/etc/ssl/client.key"),
verify="/etc/ssl/company-root-ca.crt"
)为什么 requests.session() 复用 cert 有时失效?
Session 对象会缓存 SSL 上下文,但 cert 是每次请求时才注入的,不是 Session 属性。所以不能写 s.cert = ...,必须每次调用 s.get(..., cert=...) 或提前设好默认值:
s = requests.Session()
s.cert = ("/path/to/cert.pem", "/path/to/key.pem") # ✅ 可以这样设
s.verify = "/path/to/ca.crt" # ✅ 同理
r = s.get("https://api.example.com") # ✅ 自动带上但要注意:一旦设置了 s.cert,后续所有请求都强制使用它;如果某些请求不需要 client cert,得临时覆盖:s.get(url, cert=None)。
证书文件内容变更后,Session 不会自动重载 —— 必须重建 Session 或手动 reload(Requests 不提供 reload 接口,只能重启 Python 进程或重新初始化 Session)。


















