Python使用requests库时通过证书指纹校验远程服务器证书的方法
基于requests实现证书指纹校验的方案
requests本身没有直接提供指纹校验的原生参数,你可以通过自定义HTTP传输适配器调用urllib3的内置指纹校验能力实现需求,无需引入完整的证书链文件。
前置依赖
需要安装对应依赖包:
pip install requests pyopenssl
实现代码
1. 自定义指纹校验适配器
import requests from requests.adapters import HTTPAdapter class FingerprintVerifyAdapter(HTTPAdapter): def __init__(self, target_fingerprint: str, **kwargs): # 统一格式化指纹:去除冒号、转小写,兼容不同格式的指纹输入 self.formatted_fingerprint = target_fingerprint.replace(":", "").lower() super().__init__(**kwargs) def init_poolmanager(self, *args, **kwargs): # 关闭默认的证书链校验,改用自定义指纹校验 kwargs["ssl_context"] = requests.urllib3.util.ssl_.create_urllib3_context() kwargs["ssl_context"].check_hostname = False kwargs["ssl_context"].verify_mode = 0 # 传入预设指纹,urllib3会在握手阶段自动完成校验 kwargs["assert_fingerprint"] = self.formatted_fingerprint return super().init_poolmanager(*args, **kwargs)
2. 调用示例
先提前获取目标服务器的正确SHA256/SHA1指纹,可通过openssl命令获取:
替换命令中的your.domain.com:port为实际服务器地址,SHA256指纹获取命令:openssl s_client -connect your.domain.com:port < /dev/null 2>/dev/null | openssl x509 -fingerprint -sha256 -noout如果需要SHA1指纹,把命令中的
sha256替换为sha1即可。业务代码调用:
# 替换为你实际获取的目标服务器指纹 EXPECTED_FINGERPRINT = "AB:CD:12:34:EF:56:78:90:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:0A:1B:2C:3D:4E:5F:6A:7B" # 初始化会话并挂载适配器 req_session = requests.Session() req_session.mount("https://", FingerprintVerifyAdapter(EXPECTED_FINGERPRINT)) # 正常发送请求即可,无需添加verify=False参数 response = req_session.post( url=remote_url, json=data, headers=headers ) print(response.text)
注意事项
- 指纹不匹配时请求会直接抛出SSLError异常,不会建立连接,完全符合生产环境安全要求
- 该方案安全性等同于校验完整证书链,只要提前确认的指纹为服务器真实证书的指纹,即可避免中间人攻击
- 如果使用SHA1指纹,无需修改适配器代码,仅需要替换为对应SHA1格式的指纹即可
内容的提问来源于stack exchange,提问作者kushal agrawal
相关产品推荐
相关产品推荐

