Python ssl module (OpenSSL)Python cryptography 库
错误信息
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired
搭配 OpenSSL 1.1.1、3.0 和 3.5 的 Python 中措辞完全相同,后面跟着源代码位置,例如“(_ssl.c:1082)”。有效期尚未开始的证书会报“certificate is not yet valid”。
Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_CERT_HAS_EXPIRED (10)
含义
OpenSSL 在证书链中发现了一张证书,其有效期截止时间早于本机的当前时间。通常是服务器证书没有续期,或者续期后的新证书没有被实际提供;有时是客户端通过过时 CA 证书包中已过期的根证书构建了路径,或者客户端的时钟不准。
原因
服务器证书(或中间证书)已过期
常见续期没有执行,或者执行了但服务没有重新加载。在修改客户端的任何设置之前,先检查实际提供的证书的日期。
过时的 certifi 或系统证书包
偶见固定使用旧版 certifi 的环境(或旧的操作系统镜像)可能只认识已过期版本的根证书,从而构建出过期的路径,而当前的客户端却能成功。2021年,DST Root CA X3 的交叉签名过期,许多 Python 客户端正是因此出错的。
客户端的时钟不准
偶见时钟超前的虚拟机或容器宿主机会让有效的证书看起来已经过期。如果所有网站同时出错,先检查时间。
修复方法
- 1.
查看服务器实际提供的证书
在关闭验证的情况下获取一次证书,只用于读取,然后检查 notAfter(把证书粘贴到解码器中)。不要把这个未经验证的连接用于其他任何用途。
python import socket, ssl # Read the served certificate without verifying it, to see its dates ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE with socket.create_connection(("api.example.com", 443)) as raw: with ctx.wrap_socket(raw, server_hostname="api.example.com") as tls: der = tls.getpeercert(binary_form=True) print(ssl.DER_cert_to_PEM_cert(der)) # paste into a certificate decoder - 2.
更新 certifi 或操作系统的证书包
如果服务器自身的证书没有问题,就更新客户端的根证书:对于使用 certifi 的库,运行 pip install --upgrade certifi;对于系统证书包,更新 ca-certificates 软件包。
bash python3 -m pip install --upgrade certifi python3 -c "import certifi; print(certifi.__version__, certifi.where())" - 3.
校正系统时钟
在客户端上启用 NTP(如果是容器,则在宿主机上启用)。
bash date -u sudo timedatectl set-ntp true
相关错误
curl: (60) SSL certificate problem: certificate has expiredcurl (OpenSSL backend)x509: certificate has expired or is not yet valid: current time 2026-08-20T15:4…Go crypto/x509certificate has expiredNode.js tls / https / fetchverify error:num=10:certificate has expiredOpenSSL CLI (openssl s_client / openssl verify)