Python中requests/urllib请求SSLError错误完整排查与解决方案
Python网络踩坑系列|requests/urllib SSLError 完整排查与解决方案
一、什么是 SSLError
SSLError 是 Python 在 HTTPS 请求过程中 SSL/TLS 握手失败抛出的异常。
底层来源于 OpenSSL 库,requests、urllib、aiohttp 都会抛出该类错误。
常见报错片段:
requests.exceptions.SSLError: HTTPSConnectionPool(...): Max retries exceeded with url: ...
Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002)'))
还有:证书过期、证书域名不匹配、SSL版本不兼容、CA证书缺失、代理导致SSL握手失败等。
核心本质:Python客户端无法验证服务端SSL证书合法性,SSL握手阶段直接断开。
二、常见产生SSLError的场景
- 目标网站使用自签名证书、内网测试证书,没有公共CA签发
- Python内置CA证书库缺失 / 损坏(Windows/macOS编译安装Python高频坑)
- 网络存在代理、中间人抓包工具(Fiddler、Charles)篡改证书
- 服务端SSL/TLS版本过低,和客户端OpenSSL版本不兼容
- 系统时间错误,证书判定过期
- 请求URL写错,把http写成https,服务端不支持HTTPS
三、方案1:临时关闭证书校验(开发调试用,生产不推荐)
安全警告:关闭校验会丧失证书校验能力,存在中间人劫持风险,仅限内网、调试环境,禁止线上业务直接使用。
requests 关闭证书校验
import requests
# verify=False 关闭证书校验
resp = requests.get("https://xxx.com", verify=False)
print(resp.text)
关闭后会输出大量 InsecureRequestWarning 警告,可以屏蔽警告:
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
resp = requests.get("https://xxx.com", verify=False)
urllib3 / urllib
import urllib.request
import ssl
# 创建不校验证书的上下文
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
req = urllib.request.Request("https://xxx.com")
with urllib.request.urlopen(req, context=ctx) as r:
print(r.read())
aiohttp
import aiohttp
import asyncio
async def demo():
# 关闭ssl校验
connector = aiohttp.TCPConnector(ssl=False)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get("https://xxx.com") as resp:
print(await resp.text())
asyncio.run(demo())
重点提醒:verify=False 只是绕过报错,没有真正修复证书问题,生产环境严禁使用。
四、方案2:指定CA证书文件(推荐,正式解决方案)
当目标是自签名证书,把服务端的 .crt / .pem CA根证书导出,在请求时指定证书路径。
requests 指定CA
import requests
# 传入本地根证书pem路径
resp = requests.get("https://xxx.com", verify="./ca-root.pem")
也可以给Session全局设置,后续所有请求生效:
import requests
session = requests.Session()
session.verify = "./ca-root.pem"
resp = session.get("https://xxx.com")
五、方案3:修复Python本地CA证书库
很多情况不是网站证书问题,是Python找不到CA证书。
查看requests使用的CA路径
requests依赖 certifi 包维护一套内置CA根证书集合。
import certifi print(certifi.where())
输出就是ca.pem文件路径。
升级 certifi 包,更新根证书列表
pip install -U certifi
macOS特殊坑:Python安装后需要手动执行证书安装脚本
# Python3.12示例,根据版本替换 /Applications/Python\ 3.12/Install\ Certificates.command
Windows编译安装Python,部分版本会缺失CA链,优先重装官方Python,不要用精简版。
六、方案4:SSL/TLS版本兼容问题
报错包含 SSL_ERROR_UNSUPPORTED_VERSION,代表服务端SSL版本老旧,OpenSSL新版本不再支持。
可以手动创建ssl上下文,调低允许的协议版本(谨慎,安全性下降)
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
class SslAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
ctx = ssl.create_default_context()
ctx.options |= 0x4 # OP_LEGACY_SERVER_CONNECT,兼容老旧服务端
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
ssl_context=ctx)
session = requests.Session()
session.mount("https://", SslAdapter())
resp = session.get("https://old-server.com")
OpenSSL3.0之后默认拒绝很多老旧不安全TLS版本,内网老旧设备接口很容易触发该错误。
七、方案5:代理、抓包工具导致SSLError
本地开启Fiddler、Charles抓HTTPS,Python请求会报证书错误:
- 方式A:把抓包工具根证书导入certifi的ca.pem
- 方式B:调试阶段临时设置
verify=False - 关闭代理环境变量,避免Python走到错误代理
import os # 清除代理 os.environ["HTTP_PROXY"] = "" os.environ["HTTPS_PROXY"] = ""
八、排查步骤模板(线上排错按顺序执行)
- 检查系统时间,时间不对直接导致证书校验失败。
- 浏览器访问目标URL,确认浏览器是否报证书错误,判断是服务端证书问题还是Python客户端问题。
- 升级
certifi、requests、urllib3版本。 - 测试:
verify=False请求是否成功。- 如果 verify=False 请求正常:确定是证书校验问题。
- 正式环境:导入自签名CA证书,指定verify=pem路径。
- 调试:临时关闭校验。
- 如果 verify=False 依旧报错:大概率TLS版本不兼容、网络代理、防火墙拦截。
- 如果 verify=False 请求正常:确定是证书校验问题。
- 打印完整堆栈,区分是
CERTIFICATE_VERIFY_FAILED还是版本不兼容错误。
九、开发规范与避坑
生产禁止全局 verify=False,会引入安全漏洞;自签名内网服务,优先使用指定CA证书文件。
不要使用精简版Python,容易缺失OpenSSL与CA证书。
容器化部署Python服务,镜像务必安装ca‑certificates包。
# alpine示例 RUN apk add ca-certificates
长连接Session尽量复用自定义ssl上下文,不要每次请求新建上下文。
出现SSLError不要无脑直接关闭校验,先定位根因。
十、常见错误速查表
| 报错关键字 | 根因 | 处理思路 |
|---|---|---|
| CERTIFICATE_VERIFY_FAILED | 证书校验失败 | CA缺失、自签名证书;指定pem或者升级certifi |
| SSL_ERROR_UNSUPPORTED_VERSION | TLS版本不匹配 | 自定义ssl上下文开启兼容选项 |
| SSL: CERTIFICATE_EXPIRED | 证书过期 | 服务端更新证书,客户端无法修复 |
| hostname mismatch | 证书域名不匹配 | 证书域名与访问域名不一致 |
总结
- SSLError绝大多数是SSL证书校验失败,由OpenSSL底层抛出。
verify=False只是调试手段,生产环境不要使用;自签名证书优先传入CA根证书文件。- certifi包维护Python内置CA根证书,升级certifi可以解决大部分公网证书链问题。
- 内网老旧设备会遇到TLS版本兼容问题,可以自定义ssl上下文做兼容。
- 抓包代理、系统时间错误、容器缺少ca‑certificates,也是高频诱因。
以上就是Python中requests/urllib请求SSLError错误完整排查与解决方案的详细内容,更多关于Python SSLError错误处理的资料请关注脚本之家其它相关文章!
相关文章
Python基础之hashlib模块subprocess模块logging模块
这篇文章主要为大家介绍了Python基础之hashlib模块subprocess模块logging模块示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-11-11
深入理解Python虚拟机中元组(tuple)的实现原理及源码
在本篇文章当中主要给大家介绍 cpython 虚拟机当中针对列表的实现,在 Python 中,tuple 是一种非常常用的数据类型,在本篇文章当中将深入去分析这一点是如何实现的2023-03-03


最新评论