Skip to content

解决Python SSL验证失败:无法获取本地颁发者证书

问题描述

当Python脚本尝试通过SSL/TLS建立安全连接时,可能遇到以下错误:

python
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

这表示Python无法验证服务器证书的真实性,通常由以下原因导致:

  • 本地CA证书包缺失或过期
  • Python未正确使用系统证书存储
  • 证书链不完整
  • 企业网络代理或安全软件干扰(如Zscaler)

最佳解决方案

根据多种情境推荐三种可靠方法:

方法一:使用certifi包自动配置(推荐)

  1. 安装/更新certifi包:
    bash
    pip install --upgrade certifi
  2. 在Python脚本开头配置环境变量:
    python
    import os
    import certifi
    os.environ['SSL_CERT_FILE'] = certifi.where()  # 自动获取证书路径
  3. 或在终端预配置环境变量:
    bash
    export SSL_CERT_FILE=$(python -m certifi)  # Linux/macOS
    # 永久生效:将命令加入 ~/.bashrc 或 ~/.zshrc
    
    # Windows PowerShell
    $env:SSL_CERT_FILE = (python -m certifi)

方法二:配置Python使用系统证书

python
import ssl
ssl.SSLContext.load_verify_locations(cafile=None, capath='/etc/ssl/certs/')  # Linux
# Windows: 指定企业证书路径(如C:/path/to/cert.pem)

方法三:安装pip-system-certs包

bash
pip install pip-system-certs --use-feature=truststore

场景化解决方案

环境解决方案
MacOS运行安装证书命令:
/Applications/Python\ 3.x/Install\ Certificates.command
虚拟环境在激活环境后:
python -m pip install --upgrade certifi
Homebrew终端执行:
export SSL_CERT_FILE=$(brew --prefix)/etc/ca-bundle.crt
企业代理手动添加代理证书:
os.environ['SSL_CERT_FILE'] = 'C:/path/to/proxy_cert.pem'

排查步骤

  1. 检查基础配置
    bash
    # 更新证书包
    pip install --upgrade certifi
    
    # 验证系统时间
    date  # 确保时间准确(SSL依赖精确时间)
  2. 诊断证书路径
    python
    import ssl
    print(ssl.get_default_verify_paths())  # 查看当前证书路径
  3. 测试连接
    python
    import requests
    response = requests.get('https://example.com', verify=True)  # 显式开启验证

避免的危险方法(不推荐)

python
# 禁用证书验证(重大安全风险)
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

仅在临时调试时使用该方法,生产环境必须严格避免


原理解析

当Python发起HTTPS请求时:

  1. 服务器返回SSL证书
  2. Python检查证书是否由可信任机构签发(CA)
  3. 本地CA证书包用于验证证书签名链

常见失败原因:

  • 证书包路径错误(通过SSL_CERT_FILE修复)
  • 证书包过期(通过certifi更新)
  • 中间证书缺失(需手动添加企业证书)

保持证书验证机制完整至关重要:忽略验证会使数据暴露在中间人攻击风险中。推荐使用certifi等工具自动化维护证书完整性。