外观
记录:解决 CA 证书的问题
1327字约4分钟
解决 SSL: CERTIFICATE_VERIFY_FAILED
的问题
最近使用 LangBot
或者 AstrBot
时遇到了关于 SSL
的问题:
Cannot connect to host api.github.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)')]
下面是解决的方案以及步骤:
一、在相关代码里面增加了基于 certifi
的 SSL
上下文的设置
首先确保安装了 certifi
库,如果没有安装,需要通过 pip install certifi
来安装。一般 ssl
不需要额外安装。
比如:
class SimpleGoogleGenAIClient:
def __init__(self, api_key: str, api_base: str, timeout: int = 120) -> None:
self.api_key = api_key
if api_base.endswith("/"):
self.api_base = api_base[:-1]
else:
self.api_base = api_base
self.client = aiohttp.ClientSession(trust_env=True)
self.timeout = timeout
修改后:
class SimpleGoogleGenAIClient:
def __init__(self, api_key: str, api_base: str, timeout: int = 120) -> None:
import ssl, certifi
self.api_key = api_key
if api_base.endswith("/"):
self.api_base = api_base[:-1]
else:
self.api_base = api_base
self.timeout = timeout
ssl_context = ssl.create_default_context(cafile=certifi.where())
connector = aiohttp.TCPConnector(ssl=ssl_context)
self.client = aiohttp.ClientSession(trust_env=True, connector=connector)
注意
注意: import ssl, certifi
可能不符合合 Ruff
规范,需要分别单独写在代码顶部。
后面需要定期更新 certifi
证书
如果你在虚拟环境 (venv
) 里运行 Python,可能 certifi
证书库需要更新:
pip install --upgrade certifi
然后尝试运行:
python -c "import ssl; print(ssl.get_default_verify_paths())"
如果证书路径不正确,可以手动设置:
import ssl
import certifi
ssl_context = ssl.create_default_context(cafile=certifi.where())
解决方案 2:临时禁用 SSL 验证(不推荐)
如果你只是临时调试,可以绕过 SSL 验证:
import ssl
import aiohttp
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) as session:
async with session.get("https://api.github.com") as resp:
print(await resp.text())
注意
但请注意,这种临时禁用 SSL
验证做法不安全,仅用于测试。
通过以上的方式的确解决了问题,但是别人写的代码不一定每次都会传入 SSL
上下文,需要自己每次修改代码就很麻烦。所以就有了下面的方案。
二、配置 certifi
证书
以 Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-55-generic x86_64)
为例
解决方案 3:重新安装 Python
某些情况下,Python 自带的 ssl
模块可能缺失 CA 证书。你可以尝试重新安装 Python,并确保在安装后运行:
pip install python-certifi-win32
解决方案 4:手动更新 CA 证书
如果 certifi
仍然无法解决,尝试手动更新 CA 证书:
sudo update-ca-certificates
后面我通过 python -c "import ssl; print(ssl.get_default_verify_paths())"
了解到证书的目录:
DefaultVerifyPaths
(
cafile=None,
capath='/usr/local/openssl111/certs',
openssl_cafile_env='SSL_CERT_FILE',
openssl_cafile='/usr/local/openssl111/cert.pem',
openssl_capath_env='SSL_CERT_DIR',
openssl_capath='/usr/local/openssl111/certs'
)
然后看了一眼 /usr/local/openssl111/certs
目录,结果里面是空的,什么也没有,但是考虑到之前用了下面的指令解决问题,应该不存在没有的情况。
sudo apt update && sudo apt install --reinstall ca-certificates
后面发现证书实际是在 /etc/ssl/certs/
里面,接着就直接用
sudo cp -r /etc/ssl/certs/* /usr/local/openssl111/certs/
复制粘贴了过去,最后解决了问题。
以下是我在网上找到的解决方案,适用于 Windows
,但我没有实践过。
这个错误:
Cannot connect to host api.github.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)')]
表明 Python 无法验证 GitHub API 的 SSL 证书,通常是由于 SSL 证书丢失、过期或 Python 的 certifi
证书存储未正确配置。
可能的原因
- Python 证书未安装或损坏
certifi
证书包未正确安装或损坏。
- Python 未正确配置 SSL 证书
- OpenSSL 无法找到
cacert.pem
证书文件。
- OpenSSL 无法找到
- 系统时间不正确
- 如果系统时间不正确,SSL 证书可能会被视为无效。
- 网络问题
- 代理、VPN 或防火墙可能会阻止 SSL 连接。
解决方案
方法 1:手动安装 SSL 证书
在 macOS 和 Windows 上,Python 自带了 Install Certificates.command
脚本来更新 CA 证书。
Windows/macOS
- 找到 Python 安装目录(如
C:\Program Files\PythonXX
或/Applications/Python3.X/
)。 - 运行以下脚本:
- Windows(在命令提示符
cmd
中运行):C:\Program Files\PythonXX\python.exe -m pip install --upgrade certifi
- macOS(在终端中运行):
/Applications/Python3.X/Install\ Certificates.command
- Windows(在命令提示符
如果这步解决了问题,说明你的 CA 证书丢失或损坏了。
方法 2:更新 certifi
证书
pip install --upgrade certifi
然后检查 certifi
证书路径:
import certifi
print(certifi.where()) # 查看 `cacert.pem` 位置
如果仍然出错,你可以手动替换 cacert.pem
:
- 下载最新的 CA 证书:https://curl.se/ca/cacert.pem
- 覆盖
certifi
证书文件:- 运行
python -c "import certifi; print(certifi.where())"
找到cacert.pem
位置。 - 用新下载的
cacert.pem
替换该文件。
- 运行
方法 3:指定证书路径
如果 certifi
没有正确加载,你可以在代码中手动指定证书路径:
import ssl
import certifi
ssl_context = ssl.create_default_context(cafile=certifi.where())
import urllib.request
urllib.request.urlopen("https://api.github.com", context=ssl_context)
这样可以确保 Python 使用 certifi
提供的证书文件。
方法 4:重装 Python
如果所有方法都失败,建议重装 Python:
- 卸载 Python(勾选“删除所有用户数据”)。
- 从 Python 官网下载安装最新版本:https://www.python.org/downloads/。
- 运行
Install Certificates.command
脚本(macOS 需要)。
方法 5:检查系统时间
SSL 证书验证依赖于正确的系统时间,如果你的时间不正确,会导致证书验证失败:
- Windows:
w32tm /resync
- macOS/Linux:
sudo ntpdate time.apple.com # macOS sudo timedatectl set-ntp on # Linux
总结
✅ 推荐做法:
- 运行
Install Certificates.command
(macOS/Windows)。 pip install --upgrade certifi
并替换cacert.pem
。- 手动指定
ssl.create_default_context(cafile=certifi.where())
。 - 检查系统时间是否正确。
- 重新安装 Python(如果其他方法无效)。