证书验证失败:无法获取本地颁发机构证书。
证书验证失败:无法获取本地颁发机构证书。
我正在尝试使用Python从网络中获取数据。我导入了urllib.request软件包,但在执行时出现错误:
certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
- 我正在Mac OS High Sierra上使用Python 3.7。
- 我正在尝试从CSV文件中获取数据:https://s3.amazonaws.com/assets.datacamp.com/production/course_1606/datasets/winequality-red.csv
当我将URL更改为“http”时,我能够获取数据。但我认为这避免了检查SSL证书。
于是我在互联网上查找了一个解决方案:
运行/ Applications / Python \\ 3.7 / Install \\ Certificates.command
这解决了我的问题。但是我对SSL和类似物品一无所知。您能帮助我了解它实际上是如何解决我的问题的吗?
如果可能,请向我推荐任何学习安全和证书的好资源。我是新手。
谢谢!
注意:我确实查看了链接 - openssl,python请求错误:“证书验证失败”
我的问题与链接中的问题不同,因为我想知道安装certifi
包或运行Install \\ Certificates.command
修复错误时实际发生的情况。我对安全知识了解甚少。
我在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(os.path.join(openssl_dir, 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)