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

2024-04-27 00:10:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用python从web获取数据。我为它导入了urllib.request包,但在执行时,出现错误:

certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)

当我将URL改为“http”时,我就可以获取数据。但是,我相信,这避免了检查SSL证书。

所以我上网查了一下,找到了一个解决方案: 运行/Applications/Python\ 3.7/Install\ Certificates.command

这解决了我的问题。但我对SSL之类的东西一无所知。你能帮我理解它到底是怎么解决我的问题的吗。

如果可能的话,请向我推荐任何好的资源来了解安全性和证书。我是新来的。

谢谢!

注意:我确实通过了链接-openssl, python requests error: "certificate verify failed"

我的问题与link中的问题不同,因为我想知道在安装certifi包或运行Install\ Certificates.command修复错误时实际发生了什么。我对证券的理解很差。


Tags: installtocomwebsslrequest错误certificate
3条回答

对于仍然想知道如何解决这个问题的人,我通过安装“Install Certificates.command”获得了我的

我就是这样做的

Install Certificates.commad location

只需双击该文件,等待它安装,在我的情况下,您将准备好

我在OSX上碰到了同样的问题,而我的代码在Linux上完全没有问题,你在你的问题中给出了答案!

在检查了指向/Applications/Python 3.7/Install Certificates.command的文件之后,发现这个命令用通过certifi包提供的根证书替换了默认Python安装的根证书。

certifi是一组根证书。每个SSL证书都依赖于一个信任链:您信任一个特定的证书,因为您信任该证书的父证书(您信任父证书),等等。在某些情况下,没有“父”证书,这些证书是“根”证书。对于这些人来说,除了捆绑通常受信任的根证书(通常是像“DigiCert”这样的大型信托公司),没有其他解决方案。

例如,您可以在浏览器安全设置中查看根证书(例如Firefox->;首选项->;隐私和安全->;查看证书->;权限)。

回到最初的问题,在运行.command文件之前,执行这个命令会在干净的安装上为我返回一个空列表:

import os
import ssl                                        
openssl_dir, openssl_cafile = os.path.split(      
    ssl.get_default_verify_paths().openssl_cafile)
# no content in this folder
os.listdir(openssl_dir)
# non existent file
print(os.path.exists(openssl_cafile))

这意味着OSX上没有Python安装的默认证书颁发机构。可能的默认值正是certifi包提供的值。

之后,您只需创建一个具有正确默认值的SSL上下文,如下所示(certifi.where()提供证书颁发机构的位置):

import platform
# ...

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
ssl_context.verify_mode = ssl.CERT_REQUIRED
ssl_context.check_hostname = True
ssl_context.load_default_certs()

if platform.system().lower() == 'darwin':
    import certifi
    ssl_context.load_verify_locations(
        cafile=os.path.relpath(certifi.where()),
        capath=None,
        cadata=None)

从python向url发出如下请求:

import urllib
# previous context
https_handler = urllib.request.HTTPSHandler(context=ssl_context)

opener = urllib.request.build_opener(https_handler)
ret = opener.open(url, timeout=2)

我在linux上遇到了conda的错误。我的解决办法很简单。

conda install -c conda-forge certifi

我不得不使用康达锻造,因为默认的证书似乎有问题。

相关问题 更多 >