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

2025-01-08 08:50:00
admin
原创
254
摘要:问题描述:我正在尝试使用 python 从网络获取数据。我为其导入了 urllib.request 包,但在执行时出现错误:certificate verify failed: unable to get local issuer certificate (_ssl.c:1045) 我在 Mac OS Hig...

问题描述:

我正在尝试使用 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 请求错误:“证书验证失败”

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


解决方案 1:

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

我是这样做的,

安装证书.commad 位置

只需双击该文件等待其安装,就我的情况而言,您就可以开始了

解决方案 2:

创建从操作系统证书到 Python 的符号链接对我来说是有用的:

ln -s /etc/ssl/* /Library/Frameworks/Python.framework/Versions/3.9/etc/openssl

(我在 macOS 上使用pyenv

解决方案 3:

我在 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(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)

url并向Python 发出如下请求:

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)

解决方案 4:

对于那些仍存在此问题的人:-
MacOS 上的 Python 3.6(还有其他版本吗?)附带了自己的 OpenSSL 私有副本。这意味着系统中的信任证书不再被 Python ssl 模块用作默认证书。要解决此问题,您需要在系统中安装certifi包。

您可以尝试用两种方法进行操作:

1)通过PIP:

pip install --upgrade certifi

2)如果它不起作用,请尝试运行与 Mac 版 Python 3.6 捆绑在一起的 Cerificates.command:

open /Applications/Python 3.6/Install Certificates.command

不管怎样,您现在应该已经安装了证书,并且 Python 应该能够通过 HTTPS 连接而不会出现任何问题。

希望这有帮助。

解决方案 5:

环境:Mac,Python 3.10,iTerm,

  1. 在 Finder 中搜索:安装证书.命令

在此处输入图片描述

  1. 获取信息
    在此处输入图片描述

  2. 打开方式:iTerm.app

在此处输入图片描述

  1. 双击“安装证书.command”

等待安装证书。解决它。

解决方案 6:

这适用于所有操作系统:

import ssl
import certifi
from urllib.request import urlopen

url = "https://example.com"
urlopen(url, context=ssl.create_default_context(cafile=certifi.where()))

解决方案 7:

这在 Mac OS 上对我有用:

ln -s /etc/ssl/* /Library/Frameworks/Python.framework/Versions/Current/etc/openssl/

解决方案 8:

由于问题没有标签 [macos],因此我在 ubuntu 下发布了针对同一问题的解决方案:

sudo apt install ca-certificates
sudo update-ca-certificates --fresh
export SSL_CERT_DIR=/etc/ssl/certs

解决方案来自Github 上的Zomatree。

解决方案 9:

我提供一个参考,我是cmd+space,然后输入Install Certificates.command,然后回车,过一会儿就弹出命令行界面开始安装。

 -- removing any existing file or link
 -- creating symlink to certifi certificate bundle
 -- setting permissions
 -- update complete

最后,它修复了错误。

解决方案 10:

突然,我开始在 Windows 环境中遇到这个问题。更糟糕的是,当我运行 pip 时也会出现这个问题,所以问题不在于远程服务器证书。

尝试了许多不同的方法后,我找到了结合多个答案的解决方案:

  • 将受信任的主机添加到 pip.ini:pip config set global.trusted-host "pypi.org files.pythonhosted.org pypi.python.org"(仅作为 pip install 参数传递不起作用)

  • 更新系统证书:pip install pip-system-certs(安装 python-certifi-win32 不起作用)

现在 https 请求又可以正常工作了 \o/

解决方案 11:

Certifi提供 Mozilla 精心策划的根证书集合,用于在验证 TLS 主机身份的同时验证 SSL 证书的可信度。它是从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 Certifications.command。

解决方案 12:

在我的情况下,出现此错误的原因是 OPENSSLDIR 被设置为不包含实际证书的路径,可能是由于某些升级/重新安装造成的。

要验证这是否适合您,请尝试运行:

openssl s_client -CApath /etc/ssl/certs/ -connect some-domain.com:443

如果您删除-CApath /etc/ssl/certs/并收到20错误代码,则这可能是原因。您还可以通过运行来检查 OPENSSLDIR 的设置openssl version -a

由于更改 OPENSSLDIR 需要重新编译,我发现最简单的解决方案就是在现有路径中创建一个符号链接:ln -s /etc/ssl/certs your-openssldir/certs

解决方案 13:

我使用 Homebrew 安装 Python 3.11 后遇到了此错误,使用 Pyenv(本身是用 Homebrew 安装的)安装时也遇到了此错误。

我通过重新安装 Homebrewca-certificatesopenssl软件包解决了这个问题:

brew reinstall ca-certificates openssl

解决方案 14:

将以下代码粘贴到开头:

# 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

解决方案 15:

只需运行这个:

pip install --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user pip-system-certs'

解决方案 16:

我在 Linux 上使用 conda 时遇到错误。我的解决方案很简单。

conda install -c conda-forge certifi

由于默认的 certifi 似乎有问题,我不得不使用 conda forge。

解决方案 17:

此页面是 Google 搜索“证书验证失败:无法获取本地颁发者证书”的热门页面,因此虽然这不能直接回答原始问题,但下面是针对具有相同症状的问题的修复方法。我在尝试将 TLS 添加到 xmlrpc 服务时遇到了这个问题。这需要使用相当低级的类。错误表​​明缺少证书。修复方法是在构造对象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)

在服务器中,您需要在上下文中安装中级证书:

class SecureXMLRPCServer(socketserver.TCPServer, 
        xmlrpc.server.SimpleXMLRPCDispatcher):
    # https://gist.github.com/monstermunchkin/1100226
    allow_reuse_address = True

    def __init__(self, addr, certfile, keyfile=None,
            ca_bundle=None,
            requestHandler=xmlrpc.server.SimpleXMLRPCRequestHandler,
            logRequests=True, allow_none=False, encoding=None, 
            bind_and_activate=True, ssl_version=ssl.PROTOCOL_TLSv1_2):
        self.logRequests = logRequests

        # create an SSL context
        self.context = ssl.SSLContext(ssl_version)
        self.context.load_default_certs()

        # The server is the correct place to load the intermediate CA certificates:
        self.context.load_verify_locations(ca_bundle)
        self.context.load_cert_chain(certfile=certfile, keyfile=keyfile)

        xmlrpc.server.SimpleXMLRPCDispatcher.__init__(self, allow_none, 
                encoding)
        # call TCPServer constructor
        socketserver.TCPServer.__init__(self, addr, requestHandler, 
                bind_and_activate)

        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
            flags |= fcntl.FD_CLOEXEC
            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)

    def get_request(self):
        newsocket, fromaddr = self.socket.accept()
        # create an server-side SSL socket
        sslsocket = self.context.wrap_socket(newsocket, server_side=True)
        return sslsocket, fromaddr

解决方案 18:

警告:我对证书不是很了解,但我认为这值得尽早检查。

在花费时间重新配置您的代码/包/系统之前,请确保这不是您尝试下载的服务器的问题。

我认为这个错误可能会产生误导,因为“无法获取本地颁发者证书”让它看起来像是本地机器的问题,但事实并非如此。

尝试将您尝试加载的页面更改为可能不错的页面,https://www.google.com然后查看问题是否仍然存在。此外,请使用https://www.digicert.com/help/上的搜索工具检查出现问题的域。

就我而言,DigiCert 的工具告诉我“该证书未由受信任的机构签名(根据 Mozilla 的根存储进行检查)。”这可以解释为什么我似乎已经安装了根证书,但仍然出现错误。当我测试使用 HTTPS 加载另一个网站时,没有遇到任何问题。

如果这种情况适用于您,那么我认为您可能有 3 个合理的选择(按优先顺序):1)如果服务器在您的控制之下,请修复它,2)禁用证书检查同时继续使用 HTTPS,3)跳过 HTTPS 并转到 HTTP。

解决方案 19:

我在 Windows 上也遇到过这种情况,经过一番努力,我下载了网页的 SSL 证书链

Chrome 上的步骤 -(左上角的挂锁 -> 点击“连接安全” -> 点击“证书有效”)要查看证书链,请选择证书路径。要下载每个证书,请在“证书路径”选项卡中查看证书,打开“详细信息”选项卡,然后复制到文件

下载后,打开保存证书的位置,然后编译为一个 .PEM 文件

以此为例:

    openssl x509 -in inputfilename.cer -inform DER -outform PEM  >> .pem

这个顺序很重要,从链中最低的证书开始,否则你的包将无效

最后

    response = requests.get('enter/urll/here', verify ='/path/to/created bundle')

解决方案 20:

对我来说,所有建议的解决方案都不起作用。但是,我在公司的 PC 的终端上运行代码,该 PC 安装了一个名为 ZScaler 的 IT 安全软件包。禁用 ZScaler 软件解决了我所有的问题。

解决方案 21:

对我来说,问题在于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=""

requests仅当通过 CLI (命令行界面)执行 python 时才会出现此问题。如果我运行requests.get(URL, CERT)它,它就会正常解决。

Mac OS Catalina (10.15.6)。Pyenv 3.6.11。我收到的错误消息:[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

这个答案在其他地方: https: //stackoverflow.com/a/64152045/4420657

解决方案 22:

我尝试了上述几种方法。对我有用的是:

如果您的 ~.zshrc 中没有 python 证书,请将其添加到其中:

export PIP_DEFAULT_CERT=/etc/ssl/certs/ca-certs.pem

  • 运行使用请求模块的 Python 脚本时防止出现 SSL 问题。

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certs.pem

解决方案 23:

这可能与用户遇到的问题没有直接关系,但如果您的发送请求的机器根本无法与该地址通信(可能是由于您公司或互联网提供商的安全规则),也会出现此错误。请尝试使用“curl https://your-resuouce-name”,并确保在实际修复证书之前您具有读取权限。

解决方案 24:

另一个解决方案是设置 SSL 上下文:

import ssl

def get_ssl_context() -> ssl.SSLContext:
  return ssl.SSLContext()

然后在发出新请求时使用它:

urllib.request.urlopen(request, context=get_ssl_context())

解决方案 25:

我最近在连接 MongoDB Atlas 时遇到了这个问题。我更新到了最新的certifiPython 包,现在可以正常工作了。

(python 3.8,升级至certifi 2020.4.5.1,之前为certifi版本2019.11.28)

解决方案 26:

我在 Ventura 上使用 Python 3.9-10 遇到了这个问题,尽管我已经尝试过这个:

  1. 将我的私人 CA 证书添加到 /etc/ssl/cert.pem、/etc/ssl/certs/

  2. 将我的私有 CA 证书添加到 certifi 特定的 cert.pem 文件中

  3. 将我的私人 CA 证书添加到我的钥匙串中的“系统”存储桶中

  4. 设置 REQUESTS_CA_BUNDLE=/etc/ssl/cert.pem

这使得请求有效,但 HTTPSConnection 和 urllib3 验证失败,因此还有一个地方可以添加 CA 证书:

  1. /usr/local/etc/ca-certificates/cert.pem

我相信这是因为我已经通过 brew 安装了 openssl,并且这会设置上述文件,并从 /usr/local/etc/openssl@1.1 /cert.pem 添加符号链接。

因此,如果有人在通过 brew 安装 openssl 后遇到证书验证失败,那么很可能就是这个解释。

解决方案 27:

对我有用的唯一解决方案是在 PyCharm 的“运行/调试配置”中设置SSL_CERT_DIR环境变量:

SSL_CERT_DIR=/etc/ssl/certs/

解决方案 28:

我和@Max 遇到了类似的情况,他在这里介绍了这种情况,所以我想如果其他人遇到我的情况,我可能会有所帮助。

我必须在系统上安装较新版本的 python,以支持 SSL,这需要比已安装的 openssl 更新的版本。在自定义文件夹中安装 openssl 并查看其内容后,我没有看到任何cert.pem文件。

我想获得最新的一个,因为我已经在使用python,所以我使用了certifi

pip install -U certifi

获取它的最新版本,然后运行python并在控制台中:

>>> import certifi
>>> certifi.where()
'/home/.../site-packages/certifi/cacert.pem'

之后

cp /home/.../site-packages/certifi/cacert.pem /usr/local/openssl/cert.pem

一切恢复正常,错误消失。(更新路径以匹配您的路径。)

解决方案 29:

运行 Install Certifications.command 时出现以下权限错误

PermissionError: [Errno 13] Permission denied: '../../lib/python3.10/site-packages/certifi/cacert.pem' -> 'cert.pem'
logout

但是,我通过添加解决了这个问题ssl,希望它有所帮助。

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

解决方案 30:

ln -s /etc/ssl/* /Library/Frameworks/Python.framework/Versions/Your Version/etc/openssl 它对我有用

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用