Python requests 2.25.1中session.verify=False设置不生效仍校验SSL证书
为什么会话级
verify=False不生效 这个问题是requests 2.25.1版本中典型的配置读取优先级陷阱,和你配置的自定义请求头、基础认证没有直接关联。
对照2.25.1版本requests/sessions.py的源码,请求过程中verify参数的读取逻辑完全在merge_environment_settings方法中实现,执行顺序如下:
当你调用
session.get()这类发起请求的方法时,如果没有在方法调用中显式传入verify参数(即内部形参verify为None),代码会按以下优先级确定最终的证书校验配置:
- 先读取系统环境变量
REQUESTS_CA_BUNDLE、CURL_CA_BUNDLE的有效值,只要任意一个变量存在非空值(通常是CA证书文件的绝对路径),代码就会直接把这个路径值作为证书校验的配置,完全不会再往下读取其他配置- 只有当两个环境变量都不存在时,才会读取你手动设置的
session.verify属性值如果你在请求方法调用时显式传入
verify=False,那么传入的参数值不是None,代码会完全跳过上面的环境变量读取流程,直接使用你传入的False值关闭校验——这就是为什么你单独在请求方法里传参就可以正常返回200响应的原因。
结合你的现象(自签名证书校验报错、单独传请求级verify=False生效),可以确定:你的运行环境中,一定存在REQUESTS_CA_BUNDLE或CURL_CA_BUNDLE这两个环境变量中的至少一个,指向了某份CA证书文件的路径(大概率是你之前配置自签名证书信任时设置的)。这时候哪怕你手动设置了session.verify = False,因为环境变量的优先级更高,代码根本不会走到读取你配置的会话级verify值的分支,直接用环境变量里的证书路径开启了校验,最终触发证书验证错误。
排查与解决方法
- 先验证判断:在发起请求的代码最开头,加一行打印确认环境变量值
如果输出了非空的文件路径,就完全证实了上面的逻辑判断。import os print(f"REQUESTS_CA_BUNDLE: {os.environ.get('REQUESTS_CA_BUNDLE')}") print(f"CURL_CA_BUNDLE: {os.environ.get('CURL_CA_BUNDLE')}") - 会话级
verify=False永久生效的两种方案:- 简单直接的方式:在创建Session、设置
session.verify = False之前,手动将两个相关环境变量置空,让代码在读取配置时进入读取会话属性的分支import os from requests import Session # 先清空环境变量中的CA配置 os.environ['REQUESTS_CA_BUNDLE'] = '' os.environ['CURL_CA_BUNDLE'] = '' session = Session() # 原有配置:自定义请求头、HTTPBasicAuth认证 session.verify = False - 无侵入修改全局环境变量的方式:自定义Session类,重写
merge_environment_settings方法,强制会话级verify配置优先于环境变量读取import requests class ForceVerifySession(requests.Session): def merge_environment_settings(self, url, proxies, stream, verify, cert): # 只要请求调用时没有显式传verify参数,就直接用会话级的verify配置,跳过环境变量读取 if verify is None: verify = self.verify return super().merge_environment_settings(url, proxies, stream, verify, cert) # 替换原生Session使用 session = ForceVerifySession() session.verify = False
- 简单直接的方式:在创建Session、设置
- 额外注意:requests后续多个版本都没有修改这个环境变量优先级的逻辑,哪怕升级版本,也需要注意这个配置读取规则,避免出现同类问题。
内容的提问来源于stack exchange,提问作者NPatel
相关产品推荐
相关产品推荐

