Python Requests在部分Windows机器上出现SSL证书验证失败问题求助
解决Windows服务中Requests SSL证书验证失败的跨机器一致性问题
核心问题分析
PyInstaller打包后会将certifi的cacert.pem放入临时目录C:\Windows\TEMP\_MEXXXX\certifi\,Windows服务默认以Local System账户运行,该账户对临时目录的访问权限、系统证书存储的读取权限,可能和开发机器的普通用户账户存在差异,导致证书验证失败。另外,目标机器的系统根证书链可能存在缺失,也是常见诱因。
具体解决方案
1. 打包时嵌入自定义证书链并确保路径正确
将目标URL的完整证书链(包含根证书和中间证书)保存为custom_certs.pem,放在脚本同目录,打包时强制将证书嵌入程序,代码中动态获取证书路径:
- 打包命令:
pyinstaller -F --hidden-import=win32timezone --add-data "custom_certs.pem;." DebugFile.py - 代码中获取证书路径的逻辑:
这种方式不需要依赖目标机器的系统证书,确保所有机器使用同一套证书链。import sys import os def get_valid_cert_path(): # 判断是否为打包后的运行环境 if getattr(sys, 'frozen', False): cert_dir = sys._MEIPASS else: cert_dir = os.path.dirname(os.path.abspath(__file__)) return os.path.join(cert_dir, "custom_certs.pem") # 发送请求时指定证书路径 response = requests.post( url, files=files, data=data, headers=headers, verify=get_valid_cert_path() )
2. 确保python-certifi-win32在打包后生效
python-certifi-win32的作用是让requests调用Windows系统根证书存储,但打包时可能遗漏依赖,需手动添加隐藏导入:
- 打包命令补充依赖:
pyinstaller -F --hidden-import=win32timezone --hidden-import=certifi_win32 --hidden-import=certifi_win32.wincertstore DebugFile.py - 同时,确认服务运行账户(默认Local System)有权限读取系统证书存储:
- 打开
mmc控制台,添加「证书」管理单元,选择「计算机账户」; - 检查「受信任的根证书颁发机构」中是否包含目标URL的根证书,若缺失则手动导入。
- 打开
3. 排查目标机器的证书访问问题
在服务代码中添加日志,验证证书文件的实际状态:
import logging # 配置日志到本地文件 logging.basicConfig(filename='service_ssl_debug.log', level=logging.INFO) cert_path = get_valid_cert_path() logging.info(f"证书路径:{cert_path}") logging.info(f"证书文件存在:{os.path.exists(cert_path)}") logging.info(f"证书文件可读:{os.access(cert_path, os.R_OK)}")
通过日志可以快速定位是证书路径错误、文件缺失还是权限不足的问题。
内容的提问来源于stack exchange,提问作者Milylitre
相关产品推荐
相关产品推荐

