urllib 和“SSL:CERTIFICATE_VERIFY_FAILED”错误

2024-11-26 08:36:00
admin
原创
189
摘要:问题描述:我收到以下错误:Exception in thread Thread-3: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/th...

问题描述:

我收到以下错误:

Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in        __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in  run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

这是导致此错误的代码:

if input.startswith("!web"):
    input = input.replace("!web ", "")      
    url = "https://domainsearch.p.mashape.com/index.php?name=" + input
    req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
    info = urllib2.urlopen(req).read()
    Message.Chat.SendMessage ("" + info)

我使用的 API 要求使用 HTTPS。如何才能让它绕过验证?


对于使用 Pip 时出现此错误消息,请参阅pip install failed with "connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)"。


解决方案 1:

这不是针对您的特定问题的解决方案,但我将其放在这里是因为该线程是 Google 搜索“SSL:CERTIFICATE_VERIFY_FAILED”的最佳结果,它让我陷入了徒劳无功的境地。

如果您在 OSX 上安装了 Python 3.6,并且在尝试连接到 https:// 站点时收到“SSL:CERTIFICATE_VERIFY_FAILED”错误,则可能是因为 OSX 上的 Python 3.6 根本没有证书,并且无法验证任何 SSL 连接。这是针对 OSX 上的 3.6 的更改,需要安装后步骤,即安装certifi证书包。这记录在文件ReadMe.rtf中,您可以在此找到/Applications/Python 3.6/ReadMe.rtf(另请参阅文件Conclusion.rtf和生成 macOS 安装程序的脚本build-installer.py)。

自述文件将要求您运行安装后脚本

/Applications/Python 3.10/Install Certificates.command(终端应用程序,仅此命令即可解决问题。请确保使用当前的 subversion 更新文件路径。)

(其来源是install_certificates.command),其中:

  • 首先安装 Python 包certifi,然后

  • 然后从 OpenSSL 证书文件创建到包安装的证书文件的符号链接certifi

发行说明包含更多信息:https ://www.python.org/downloads/release/python-360/

在较新版本的 Python 中,有更多关于此内容的文档:

解决方案 2:

如果你只是想绕过验证,你可以创建一个新的SSLContext。默认情况下,新创建的上下文使用CERT_NONE。

请小心处理,如第17.3.7.2.1节所述

直接调用 SSLContext 构造函数时,CERT_NONE 是默认值。由于它不对另一方进行身份验证,因此它可能不安全,尤其是在客户端模式下,大多数时候您希望确保与之通信的服务器的真实性。因此,在客户端模式下,强烈建议使用 CERT_REQUIRED。

但是如果您只是因为其他原因希望它现在工作,您可以执行以下操作,您也必须import ssl这样做:

input = input.replace("!web ", "")      
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' })
gcontext = ssl.SSLContext()  # Only for gangstars
info = urllib2.urlopen(req, context=gcontext).read()
Message.Chat.SendMessage ("" + info)

这应该可以解决你的问题,但你并没有真正解决任何问题,但你不会看到,[SSL: CERTIFICATE_VERIFY_FAILED]因为你现在没有验证证书!

除上述内容外,如果您想进一步了解为什么会出现这些问题,您可能需要查看PEP 476。

本 PEP 建议默认启用 X509 证书签名验证以及 Python HTTP 客户端的主机名验证,但每次调用时均可选择退出。此更改将应用​​于 Python 2.7、Python 3.4 和 Python 3.5。

有一个建议退出,它与我上面的建议并没有什么不同:

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

它还通过monkeypatching提供了一个非常不推荐的选项,这在 python 中并不常见:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

它使用创建未经验证的上下文的函数覆盖创建上下文的默认函数。

请注意 PEP 中所述的内容:

本指南主要针对希望在尚不支持 HTTPS 连接证书验证的旧环境中采用实施此 PEP 的较新版本的 Python 的系统管理员。例如,管理员可以通过将上述 monkeypatch 添加到 Python 标准操作环境中的 sitecustomize.py 来选择退出。应用程序和库不应在整个过程中进行此更改(除非是为了响应系统管理员控制的配置设置)。

如果您想阅读一篇关于为什么不在软件中验证证书不好的论文,您可以在这里找到它!

解决方案 3:

扩展 Craig Glennie 的回答:

在 MacOs Sierra 上的 Python 3.6.1 中

在 bash 终端中输入此命令解决了问题:

pip install certifi
/Applications/Python 3.6/Install Certificates.command

解决方案 4:

在 Windows 上,Python 不会查看系统证书,而是使用位于 的自己的证书?libsite-packagescertificacert.pem

解决您问题的方法:

  1. 下载域验证证书为 .crt 或 pem 文件

  2. 在编辑器中打开文件并将其内容复制到剪贴板

  3. 找到您的cacert.pem位置:from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)

  4. 编辑该cacert.pem文件并将您的域验证证书粘贴到文件末尾。

  5. 保存文件并享受请求!

解决方案 5:

urllib.request.urlopen尽管我在Python 3.4、3.5 和 3.6中使用,但我也遇到了类似的问题。 (根据 Python 2文档页面urllib2开头的注释,这是 Python 3 等效版本的一部分。)urllib2

我的解决方案是pip install certifi安装certifi,它具有:

...精心策划的根证书集合,用于在验证 TLS 主机的身份的同时验证 SSL 证书的可信度。

然后,在我之前的代码中:

import urllib.request as urlrq

resp = urlrq.urlopen('https://example.com/bar/baz.html')

我修改为:

import urllib.request as urlrq
import certifi

resp = urlrq.urlopen('https://example.com/bar/baz.html', cafile=certifi.where())

如果我正确阅读了urllib2.urlopen文档,它也有一个cafile参数。因此,urllib2.urlopen([...], certifi.where())可能也适用于 Python 2.7。


更新(2020-01-01):从 Python 3.6 开始,参数cafileurlopen被弃用,context而应改为指定参数。我发现以下内容在 3.5 到 3.8 上同样有效:

import urllib.request as urlrq
import certifi
import ssl

resp = urlrq.urlopen('https://example.com/bar/baz.html', context=ssl.create_default_context(cafile=certifi.where()))

解决方案 6:

我针对 Mac OS X 的解决方案:

  1. 使用从 Python 语言官方网站https://www.python.org/downloads/下载的原生应用 Python 安装程序升级到 Python 3.6.5

我发现这个安装程序在更新新 Python 的链接和符号链接方面比 homebrew 做得好得多。

  1. "./Install Certificates.command"使用刷新后的 Python 3.6 目录中的证书安装新证书

cd "/Applications/Python 3.6/"
sudo "./Install Certificates.command"

解决方案 7:

您可以尝试将其添加到您的环境变量中:

PYTHONHTTPSVERIFY=0 

请注意,这将禁用所有HTTPS 验证,因此这是一种强硬的方法,但是,如果不需要验证,它可能是一种有效的解决方案。

解决方案 8:

我在我的一台 Linux 机器上遇到了类似的问题。生成新证书并导出指向证书目录的环境变量可以解决这个问题:

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

解决方案 9:

我认为您有几种方法可以解决此问题。我在下面提到了 5 种方法:

  1. 您可以为每个请求定义上下文,并在每个请求上传递上下文以供使用,如下所示:

import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)
  1. 或 在 中设置证书文件environment

import os
import certifi
import urllib
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
result = urllib.request.urlopen('https://www.example.com')

  1. 或更换create default https context方法:

import certifi
import ssl
ssl._create_default_https_context = lambda: ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com')
  1. 或者如果您使用Linux机器,生成新的证书并导出指向证书目录的环境变量即可解决问题。

$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
  1. 或者如果你使用Mac机器,生成新证书

$ cd "/Applications/$(python3 --version | awk '{print $2}'| awk  -F. '{print "Python " $1"."$2}')"
$ sudo "./Install Certificates.command"

解决方案 10:

import requests
requests.packages.urllib3.disable_warnings()

import ssl

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

取自此处https://gist.github.com/michaelrice/a6794a017e349fc65d01

解决方案 11:

就像我在评论中所写的那样,这个问题可能与这个 SO 答案有关。

简而言之:有多种方法可以验证证书。OpenSSL 使用的验证与您系统上受信任的根证书不兼容。Python 使用 OpenSSL。

您可以尝试获取Verisign Class 3 Public Primary Certification Authority缺少的证书,然后cafile根据Python 文档使用该选项:

urllib2.urlopen(req, cafile="verisign.pem")

解决方案 12:

$ cd $HOME
$ wget --quiet https://curl.haxx.se/ca/cacert.pem
$ export SSL_CERT_FILE=$HOME/cacert.pem

来源:https://access.redhat.com/articles/2039753

解决方案 13:

Anaconda 的解决方案

我的设置是 MacOS 上的 Anaconda Python 3.7,带有代理。路径不同。

  • 这是获取正确证书路径的方法:

import ssl
ssl.get_default_verify_paths()

在我的系统上生成

Out[35]: DefaultVerifyPaths(cafile='/miniconda3/ssl/cert.pem', capath=None,
 openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/miniconda3/ssl/cert.pem',
 openssl_capath_env='SSL_CERT_DIR', openssl_capath='/miniconda3/ssl/certs')

一旦您知道证书的去向,就可以将代理使用的证书连接到该文件的末尾。

我已经设置了 conda 与我的代理一起工作,通过运行:

conda config --set ssl_verify <pathToYourFile>.crt

如果您不记得您的证书在哪里,您可以在以下位置找到它~/.condarc

ssl_verify: <pathToYourFile>.crt

现在将该文件连接到末尾/miniconda3/ssl/cert.pem
,请求就应该可以工作了,特别sklearn.datasets是类似的工具也应该可以工作。

进一步警告

其他解决方案不起作用,因为 Anaconda 设置略有不同:

  • 该路径Applications/Python 3.X根本就不存在。

  • 以下命令提供的路径是错误路径

from requests.utils import DEFAULT_CA_BUNDLE_PATH
DEFAULT_CA_BUNDLE_PATH

解决方案 14:

我需要添加另一个答案,因为就像 Craig Glennie 一样,由于网络上有许多帖子提到这个问题,我进行了徒劳无功的追寻。

我正在使用 MacPorts,我原本以为是 Python 的问题,其实是 MacPorts 的问题:它在安装 openssl 时没有安装根证书。解决方案是,如这篇博文port install curl-ca-bundle中所述。

解决方案 15:

我在这里找到了这个

我找到了这个解决方案,在源文件的开头插入此代码:

import ssl

try:
   _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

此代码使验证撤消,从而不验证 ssl 认证。

解决方案 16:

Python 2.7.12(默认,2016 年 7 月 29 日,15:26:22)修复了上述问题。此信息可能对其他人有帮助。

解决方案 17:

我很惊讶所有这些说明都没有解决我的问题。尽管如此,诊断是正确的(顺便说一句,我使用的是 Mac 和 Python3.6.1)。因此,总结一下正确的部分:

  • Apple 将在 Mac 上放弃 OpenSSL

  • Python 现在使用自己的一套 CA 根证书

  • 二进制 Python 安装提供了一个脚本来安装 Python 所需的 CA 根证书(“/Applications/Python 3.6/Install Certifications.command”)

  • 有关详细信息,请参阅“/Applications/Python 3.6/ReadMe.rtf”

对我来说,脚本不起作用,所有那些 certifi 和 openssl 安装也修复失败。可能是因为我有多个 python 2 和 3 安装,以及许多虚拟环境。最后,我需要手动修复它。

pip install certifi   # for your virtualenv
mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl
cp -a <your virtualenv>/site-package/certifi/cacert.pem \n  /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/cert.pem

如果这仍然失败,那么也重新安装 OpenSSL。

port install openssl

解决方案 18:

SSL:CERTIFICATE_VERIFY_FAILED 错误也可能是因为ca-certificatesLinux 上的软件包中缺少中间证书。例如,在我的情况下,软件包中缺少中间证书“ DigiCert SHA2 Secure Server CAca-certificates ”,尽管 Firefox 浏览器包含它。您可以通过直接在wget导致此错误的 URL 上运行命令来找出缺少哪个证书。然后,您可以从证书颁发机构的官方网站(例如,在我的情况下为https://www.digicert.com/digicert-root-certificates.htm)搜索此证书的 CRT 文件的相应链接。现在,要包含您的情况下缺少的证书,您可以使用 CRT 文件下载链接运行以下命令:

wget https://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

mv DigiCertSHA2SecureServerCA.crt DigiCertSHA2SecureServerCA.der

openssl x509 -inform DER -outform PEM -in DigiCertSHA2SecureServerCA.der -out DigicertSHA2SecureServerCA.pem.crt

sudo mkdir /usr/share/ca-certificates/extra

sudo cp DigicertSHA2SecureServerCA.pem.crt /usr/share/ca-certificates/extra/

sudo dpkg-reconfigure ca-certificates

此后,您可以再次wget使用 URL 以及 pythonurllib包进行测试。有关更多详细信息,请参阅: https: //bugs.launchpad.net/ubuntu/+source/ca-certificates/+bug/1795242

解决方案 19:

看看

/Applications/Python 3.6/Install Certificates.command

您也可以在 Finder 中转到Applications文件夹并单击Certificates.command

解决方案 20:

我有点羞愧地低下了头,因为我遇到了同样的问题,只不过在我的情况下,我访问的 URL 是有效的,证书也是有效的。无效的是我与网络的连接。我未能将代理详细信息添加到浏览器(在本例中为 IE)。这阻止了验证过程的正确进行。

添加代理详细信息后,我的 Python 就非常高兴了。

解决方案 21:

对于Centos 6/7、Fedora上的Python 3.4+,只需通过以下方式安装受信任的 CA:

  1. 将 CA.crt 复制到/etc/pki/ca-trust/source/anchors/

  2. update-ca-trust force-enable

  3. update-ca-trust extract

解决方案 22:

像你一样,我在我的旧 iMac(OS X 10.6.8)上使用 python 2.7,我也遇到了这个问题,使用 urllib2.urlopen:

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]

我的程序运行正常,没有 SSL 证书问题,但突然(下载程序后)程序崩溃了,并出现此 SSL 错误。

问题在于使用的python版本:

  1. https://www.python.org/downloads和 python-2.7.9-macosx10.6.pkg没有问题

  2. Homebrew 工具安装的问题:“brew install python”,版本位于 /usr/local/bin。

其中有一章,名为Certificate verification and OpenSSL [CHANGED for Python 2.7.9]/Applications/Python 2.7/ReadMe.rtf详细地解释了这个问题。

因此,请检查、下载并将正确版本的 python 放入您的 PATH 中。

解决方案 23:

带有 centOS 7 的 Amazon EC2 上的 Python 2.7

我必须设置环境变量SSL_CERT_DIR来指向我的ca-bundle,它位于/etc/ssl/certs/ca-bundle.crt

解决方案 24:

在某些情况下,您无法使用不安全的连接或将 SSL 上下文传递到 urllib 请求中。这是我基于
https://stackoverflow.com/a/28052583/6709778的解决方案

如果你想使用自己的证书文件

import ssl

def new_ssl_context_decorator(*args, **kwargs):
    kwargs['cafile'] = '/etc/ssl/certs/ca-certificates.crt'
    return ssl.create_default_context(*args, **kwargs)

ssl._create_default_https_context = ssl._create_unverified_context

或者您可以使用 certifi 的共享文件

def new_ssl_context_decorator(*args, **kwargs):
    import certifi
    kwargs['cafile'] = certifi.where()
    return ssl.create_default_context(*args, **kwargs)

解决方案 25:

M1 MacOS 解决方案

  1. 要调查哪些路径用于查找 SSL 证书,请运行以下 Python 代码:

import ssl
ssl.get_default_verify_paths()

对我来说这返回:

DefaultVerifyPaths(cafile = None,capath = None,openssl_cafile_env ='SSL_CERT_FILE',openssl_cafile ='/opt/local/libexec/openssl3/etc/openssl/cert.pem',openssl_capath_env ='SSL_CERT_DIR',openssl_capath ='/opt/local/libexec/openssl3/etc/openssl/certs')

这些路径不正确。

  1. 然后我重新安装了 OpenSSL,以找出它的安装位置。我运行了:

brew uninstall --ignore-dependencies openssl && brew install openssl

查看上述命令的输出,它将打印 cert.pem 和 certs 文件夹的路径(在步骤 3 中使用)。

  1. 为了让我的系统知道正确的路径,我设置了以下环境变量:

export SSL_CERT_FILE=/opt/homebrew/etc/openssl@3/cert.pem
export SSL_CERT_DIR=/opt/homebrew/etc/openssl@3/certs

(将这些行添加到您的.profile文件中以永久设置变量)

解决方案 26:

PyOpenSSL使用对我有用的安装pip(无需转换为 PEM):

pip install PyOpenSSL

解决方案 27:

我通过关闭 Fiddler(一个 HTTP 调试代理)解决了这个问题,检查您是否启用了代理,然后重试。

解决方案 28:

就我而言,我收到此错误是因为requests版本urllib3不兼容,在安装过程中出现以下错误:

ERROR: requests 2.21.0 has requirement urllib3<1.25,>=1.21.1, but you'll have urllib3 1.25 which is incompatible.
pip install 'urllib3<1.25' --force-reinstall

成功了。

解决方案 29:

另一个 Anaconda 解决方案。我在 macOS 上的 Python 2.7 环境中收到 CERTIFICATE_VERIFY_FAILED 错误。结果发现 conda 路径有问题:

基础(3.7)环境:

>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile='/usr/local/anaconda3/ssl/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/ssl/certs')

2.7 环境(路径不存在!):

DefaultVerifyPaths(cafile='', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/envs/py27/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/envs/py27/ssl/certs')

修复:

cd /usr/local/anaconda3/envs/py27/
mkdir ssl
cd ssl
ln -s ../../../ssl/cert.pem

解决方案 30:

我在尝试读取 .pdf 文件时遇到了这个问题,它已修复verify=Falseresponse = requests.get(pdf_url, verify=False)但只有服务器受信任时这才是安全的

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

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用