这是Python HTTP客户端(如requests)验证远端HTTPS服务证书失败所致,需通过REQUESTS_CA_BUNDLE环境变量或verify参数指定CA证书路径,而非配置Flask的ssl_context。

Flask run 时提示 ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] 怎么办
这不是 Flask 自己报的错,而是底层 urllib 或你代码里用 requests、httpx 等发 HTTPS 请求时,系统找不到可信 CA 证书,或证书链不完整导致的。常见于 macOS(系统自带 OpenSSL 不读 Mac Keychain)、Linux(无预装 ca-certificates)或 Docker 容器环境。
解决方向不是“配 Flask 的 context”,而是让 Python 进程能验证远端 HTTPS 服务的证书——比如你调用了微信 API、支付网关、第三方 OAuth 接口等。
- 先确认出问题的代码位置:是
requests.get("https://...")?还是httpx.Client()?或是ssl.create_default_context()被显式调用? - 临时绕过(仅开发):
requests.get(url, verify=False),但会触发InsecureRequestWarning,且生产禁用 - 真正修复:把系统或自定义 CA 证书路径告诉 Python,通过环境变量或代码指定
如何让 requests 使用指定的 CA 证书文件(如 fullchain.pem)
requests 默认读取 certifi.where() 返回的证书包,但你可以用 CERT_PATH 环境变量或 verify= 参数覆盖它。注意:verify= 后跟的是「CA bundle 文件路径」,不是你的域名私钥或 cert.pem 单文件。
- 如果你有 Let’s Encrypt 的
fullchain.pem(即cert.pem+ 中间证书),它仍不能直接当 CA bundle 用;需确保它包含根和中间证书,且格式为 PEM、顺序为「叶子→中间→根」 - 更稳妥做法:用系统级 CA 包,比如 Ubuntu 上
/etc/ssl/certs/ca-certificates.crt,或用certifi提供的:python -c "import certifi; print(certifi.where())" - 代码中指定:
requests.get("https://api.example.com", verify="/path/to/ca-bundle.crt") - 全局生效(推荐):
export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"(Linux/macOS)或set REQUESTS_CA_BUNDLE=C:\cacert.pem(Windows)
为什么配置 ssl_context 参数对解决证书验证失败无效
Flask 的 ssl_context(如 ssl_context=("cert.pem", "key.pem"))只控制「本机作为 HTTPS 服务器时的证书」,也就是浏览器访问 https://localhost:5000 时用的证书。它完全不影响 Flask 应用作为「HTTP 客户端」去请求其他 HTTPS 地址时的证书验证行为。
立即学习“Python免费学习笔记(深入)”;
- 混淆点:两个方向完全不同——一个是「我对外提供 HTTPS」,一个是「我向别人发起 HTTPS」
- 如果你在 Flask 路由里调用
requests.post("https://pay.example.com")报错,改app.run(ssl_context=...)没有任何作用 - 同理,
context = ssl.create_default_context()后手动 load_verify_locations(),也得用在你自己的urllib.request.urlopen()或http.client调用里,而非 Flask 启动参数
Docker 部署时 SSL 验证失败的典型修复方式
Alpine 或 slim 镜像(如 python:3.11-slim)默认不含 CA 证书,certifi 包虽有内置证书,但某些内网环境或自签名服务仍需额外注入。
- 基础修复:Dockerfile 中安装系统证书包:
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*(Debian/Ubuntu) - Alpine:用
apk add ca-certificates,再update-ca-certificates - 若需追加私有 CA:
COPY my-company-root.crt /usr/local/share/ca-certificates/→update-ca-certificates - 验证是否生效:
docker exec -it myapp python -c "import requests; print(requests.get('https://httpbin.org/get').status_code)"
最常被忽略的一点:你以为在修 Flask 的 SSL 配置,其实要修的是 Python HTTP 客户端的证书信任链。定位清楚「谁在验证谁的证书」,比盲目塞路径有用得多。


















