证书验证失败:无法获取本地颁发者证书,没什么异常

0 投票
2 回答
42 浏览
提问于 2025-04-12 17:56

我在用Python的requests库时遇到了一个错误:

证书验证失败:无法获取本地颁发者证书。

这是我的代码:

import requests

url = 'https://sha256.badssl.com'

cert_path = 'certificate.pem'

response = requests.get(url, verify=cert_path)

文件certificate.pem包含了:

-----BEGIN CERTIFICATE-----

...

-----END CERTIFICATE-----

这是通过以下方式得到的:

openssl s_client -connect sha256.badssl.com:443

certificate.pem和我的main.py在同一个文件夹里。

我试过用绝对路径。

我尝试过Python版本3.10.12和3.12.2。

我已经查看过文档,也看过同样的问题,在这里

我还尝试过换一个WiFi。

我没有运行任何代理。

2 个回答

0

我觉得你遇到了几个问题,因为 https://badssl.com 这个网站有有效的证书,所以你不应该在访问这个网址时出现证书错误。这说明你可能缺少一些基本的受信任证书颁发机构的列表。

那么,我们来仔细看看这个问题。

如果你通过下面的方式获取服务器的证书:

openssl s_client -connect sha256.badssl.com:443 < /dev/null > certificate

那么你会得到一个单独的证书:

$ grep BEGIN certificate
-----BEGIN CERTIFICATE-----

这个证书不是自签名证书:

$ openssl x509 -in certificate -noout -subject -issuer certificate
subject=CN = *.badssl.com
issuer=C = US, O = Let's Encrypt, CN = R3

这意味着在 requests.getverify 参数中使用它是没有意义的;你需要的是颁发者的证书。当你使用 openssl s_client 来获取远程证书时,可能需要提供 -showcerts 选项,这样可以显示服务器发送的整个证书链:

openssl s_client -showcerts -connect sha256.badssl.com:443 < /dev/null > certificate

现在你会发现我们有多个证书:

$ grep BEGIN certificate
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----

第一个证书是我们之前看到的,但第二个证书是:

subject=C = US, O = Let's Encrypt, CN = R3
issuer=C = US, O = Internet Security Research Group, CN = ISRG Root X1

如果我们把这个新文件当作我们的CA捆绑包使用,它就能正常工作:

>>> import requests
>>> requests.get('https://badssl.com/', verify='certificate')
<Response [200]>

值得注意的是,远程服务器提供的证书链可能不包括根证书。在这种情况下,你需要直接从证书颁发机构获取根证书(例如,https://letsencrypt.org/certificates/ 是 Let's Encrypt 的根证书)。

0

这个命令:

openssl s_client -showcerts -connect sha256.badssl.com:443 < /dev/null > certificate

会提供两个证书,但请求需要第三个证书。

如果想在Firefox浏览器上获取这个证书,可以按照以下步骤操作:

点击地址栏里的小锁图标

然后点击查看证书

在第三个证书部分,点击PEM(证书)

不过我不知道怎么用openssl获取这个证书。如果有人知道怎么做,那就太好了。

撰写回答