我正在尝试使用python从网络获取数据。我为此导入了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"
我的问题不同于链接中的问题,因为我想知道在安装certifi
软件包或运行Install\ Certificates.command
来修复错误时实际发生的情况。我对证券知之甚少。
答案 0 :(得分:11)
答案 1 :(得分:6)
我想提供参考。我使用cmd +空格,然后键入Install Certificates.command
,然后按Enter。片刻之后,命令行界面弹出,开始安装。
-- removing any existing file or link
-- creating symlink to certifi certificate bundle
-- setting permissions
-- update complete
最后,它修复了错误。
答案 2 :(得分:3)
此页面是Google在“证书验证失败:无法获取本地发行者证书”方面的热门搜索,因此虽然这不能直接回答原始问题,但下面是针对具有相同症状的问题的解决方案。我在尝试将TLS添加到xmlrpc服务时遇到了这个问题。这需要使用相当低级的<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="app">
<div class="loading"></div>
</div>
</body>
类。该错误表明证书丢失。解决方法是在构造ssl.SSLContext
对象时做几件事:
首先,在客户端中:
SSLContext
在服务器中,您需要在上下文中安装中间证书:
def get_client():
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Load the default certs:
context.load_default_certs()
# Optionally, install the intermediate certs.
# This _should_ be handled by the server, but
# maybe helpful in some cases.
# context.load_verify_locations('path/to/ca_bundle.crt')
return xmlrpc.client.ServerProxy('https://server.yourdomain.com/', context=context)
答案 3 :(得分:3)
在开始时粘贴以下代码:
# paste this at the start of code
import ssl
try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
pass
else:
ssl._create_default_https_context = _create_unverified_https_context
答案 4 :(得分:3)
创建从操作系统证书到 Python 的符号链接对我有用:
ln -s /etc/ssl/* /Library/Frameworks/Python.framework/Versions/3.9/etc/openssl
(我使用的是 macOS,使用 pyenv
)
答案 5 :(得分:2)
对于那些仍然存在此问题的人:- MacOS上的Python 3.6(还有其他版本吗?)带有自己的OpenSSL私有副本。这意味着Python ssl模块不再将系统中的信任证书用作默认值。要解决此问题,您需要在系统中安装 certifi 软件包。
您可以尝试通过两种方式进行操作:
1)通过PIP:
pip install --upgrade certifi
2)如果不起作用,请尝试运行Python 3.6 for Mac附带的Cerificates.command:
open /Applications/Python\ 3.6/Install\ Certificates.command
一种或另一种方式,您现在应该已经安装了证书,并且Python应该能够通过HTTPS连接而没有任何问题。
希望这会有所帮助。
答案 6 :(得分:1)
对我来说,问题是我在REQUESTS_CA_BUNDLE
中设置了.bash_profile
/Users/westonagreene/.bash_profile:
...
export REQUESTS_CA_BUNDLE=/usr/local/etc/openssl/cert.pem
...
一旦我将REQUESTS_CA_BUNDLE
设置为空白(即从.bash_profile中删除),requests
就会重新工作。
export REQUESTS_CA_BUNDLE=""
该问题仅在通过CLI(命令行界面)执行python requests
时出现。如果我运行requests.get(URL, CERT)
,就可以解决。
Mac OS Catalina(10.15.6)。
3.6.11的Pyenv。
我收到的错误消息:[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)
答案 7 :(得分:1)
Certifi
提供 Mozilla 精心策划的根证书集合,用于验证 SSL 证书的可信度,同时验证 TLS 主机的身份。它是从 Requests 项目中提取的。
pip install certifi
或者运行下面的程序代码:
# install_certifi.py
#
# sample script to install or update a set of default Root Certificates
# for the ssl module. Uses the certificates provided by the certifi package:
# https://pypi.python.org/pypi/certifi
import os
import os.path
import ssl
import stat
import subprocess
import sys
STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
| stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
| stat.S_IROTH | stat.S_IXOTH )
def main():
openssl_dir, openssl_cafile = os.path.split(
ssl.get_default_verify_paths().openssl_cafile)
print(" -- pip install --upgrade certifi")
subprocess.check_call([sys.executable,
"-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"])
import certifi
# change working directory to the default SSL directory
os.chdir(openssl_dir)
relpath_to_certifi_cafile = os.path.relpath(certifi.where())
print(" -- removing any existing file or link")
try:
os.remove(openssl_cafile)
except FileNotFoundError:
pass
print(" -- creating symlink to certifi certificate bundle")
os.symlink(relpath_to_certifi_cafile, openssl_cafile)
print(" -- setting permissions")
os.chmod(openssl_cafile, STAT_0o775)
print(" -- update complete")
if __name__ == '__main__':
main()
Brew 没有运行 Mac 的 Python3 包中的 Install Certificates.command。
答案 8 :(得分:0)
我在OSX上遇到了同样的问题,而我的代码在Linux上完全没问题,您给出了问题的答案!
在检查了您指向/Applications/Python 3.7/Install Certificates.command
的文件之后,事实证明此命令将{Python}安装的根证书替换为certifi
软件包附带的根证书。
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)
答案 9 :(得分:0)
我在Linux上的conda错误。我的解决方法很简单。
conda install -c conda-forge certifi
由于默认证书似乎有问题,我不得不使用conda伪造。
答案 10 :(得分:0)
这适用于所有操作系统:
HttpResponseMessage responseMessage = new HttpResponseMessage()
{
Content = new StringContent(JsonConvert.SerializeObject(message)),
//StatusCode = System.Net.HttpStatusCode.Forbidden
StatusCode = System.Net.HttpStatusCode.Unauthorized
};
答案 11 :(得分:0)
我最近在连接MongoDB Atlas时遇到了这个问题。我更新到了最新的certifi
python软件包,现在可以使用了。
(python 3.8,升级到certifi 2020.4.5.1,以前的证书版本为2019.11.28)
答案 12 :(得分:0)
在我的情况下,此错误的原因是 OPENSSLDIR 设置为不包含实际证书的路径,可能是由某些升级/重新安装引起的。
要验证您是否属于这种情况,请尝试运行:
openssl s_client -CApath /etc/ssl/certs/ -connect some-domain.com:443
如果您删除 -CApath /etc/ssl/certs/
并获得 20
错误代码,则这可能是原因。您还可以通过运行 openssl version -a
来检查 OPENSSLDIR 的设置。
由于更改 OPENSSLDIR 需要重新编译,我发现最简单的解决方案是在现有路径中创建一个符号链接:ln -s /etc/ssl/certs your-openssldir/certs
答案 13 :(得分:0)
警告:我对证书不是很了解,但我认为这值得尽早检查。
在花费任何时间重新配置您的代码/包/系统之前,请确保您尝试从中下载的服务器没有问题。
我认为该错误可能具有误导性,因为“无法获得本地颁发者证书”使您的本地计算机似乎存在问题,但情况不一定如此。
尝试将您尝试加载的页面更改为可能不错的页面,例如 https://www.google.com
,然后查看问题是否仍然存在。此外,请使用 https://www.digicert.com/help/ 中的搜索工具检查给您带来问题的域。
就我而言,DigiCert 的工具告诉我“证书不是由受信任的机构签署的(对照 Mozilla 的根存储进行检查)。”这将解释为什么我似乎安装了根证书但仍然有错误。当我测试使用 HTTPS 加载其他站点时,我没有遇到任何问题。
如果这种情况适用于您,那么我认为您可能有 3 个逻辑选项(按优先顺序排列):1) 如果服务器在您的控制之下,则修复它,2) 在继续使用 HTTPS 的同时禁用证书检查,3)跳过 HTTPS 并转到 HTTP。