urllib和"SSL:CERTIFICATE_VERIFY_FAILED"错误

use*_*476 250 python ssl urllib ssl-certificate python-2.7

我收到以下错误:

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)>
Run Code Online (Sandbox Code Playgroud)

这是导致此错误的代码:

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)
Run Code Online (Sandbox Code Playgroud)

我正在使用的API要求我使用HTTPS.如何绕过验证?

Cra*_*nie 337

这不是你特定问题的解决方案,但是我把它放在这里是因为这个帖子是"SSL:CERTIFICATE_VERIFY_FAILED"的Google最高结果,它引导我进行疯狂的追逐.

如果您在OSX上安装了Python 3.6并且在尝试连接到https://站点时收到"SSL:CERTIFICATE_VERIFY_FAILED"错误,则可能是因为OSX上的Python 3.6根本没有证书,并且无法验证任何SSL连接.这是OSX上3.6的更改,需要安装后步骤,安装certifi证书包.这在ReadMe中有记录,您可以在其中找到/Applications/Python\ 3.6/ReadMe.rtf

ReadMe将让您运行此安装后脚本,该脚本只需安装certifi:/Applications/Python\ 3.6/Install\ Certificates.command

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

  • 直接运行/ Applications/Python\3.6/Install\Certificates.command解决我在OSX上的问题.谢谢. (89认同)
  • 这为我修复了 `/Applications/Python\ 3.7/Install\ Certificates.command` 直接在 `terminal` 中运行它!谢谢@CraigGlennie 和@muyong 我很欣赏把它放在这里的“开箱即用”! (6认同)
  • 这正是解决方案!最直接的! (4认同)
  • macOS Mojave上的Python 3.7:在这里不起作用。我已卸载/重新安装/运行安装证书,重新启动等。对我不起作用 (4认同)
  • 这是纯金. (3认同)
  • 我正在使用OS X El Capitan 10.11.6,Python 3.6.0,这个解决方案非常有效. (2认同)
  • 我正在使用macOS Sierra 10.12.5,Python 3.6.1,这个解决方案非常有效. (2认同)
  • 对 Python3.7 和 macOS 10.14.4 仍然没有帮助 (2认同)
  • 任何人都可以在 Debian 或同等设备上使用它?尝试安装 python-certfi 但没有用。 (2认同)
  • 我找不到 /Application/Python 3.6/ 目录。我安装了蟒蛇。谁能告诉我如何使用安装了 Anaconda 的 python 来做到这一点? (2认同)
  • 如果您将 pyenv 与 virtualenv 一起使用,这是如何工作的?当我转到 ~/.pyenv/versions/3.6.0/ 时,我没有看到安装目录。 (2认同)
  • Python 3.11 和 MacOS Monterey 12.6 仍然需要这样做。然而,它的作用就像一个魅力。 (2认同)

Noe*_*lkd 263

如果您只想绕过验证,则可以创建新的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)
Run Code Online (Sandbox Code Playgroud)

这应该解决你的问题,但你并没有真正解决任何问题,但你不会看到,[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)
Run Code Online (Sandbox Code Playgroud)

它还有一个非常气馁的选项,通过monkeypatching,你不常在python中看到:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context
Run Code Online (Sandbox Code Playgroud)

其中使用函数覆盖创建上下文的默认函数以创建未验证的上下文.

请注意PEP中所述:

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

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

  • ssl._create_default_https_context = ssl._create_unverified_context这对我很有用,正如Noelkd提到的那样.由于我们是HP打印机的内部网站点...纯粹用于抓取...我们使用此方法没有问题. (3认同)

jnP*_*nPy 64

扩展Craig Glennie的答案(抱歉没有足够的声誉评论):

在MacO Sierra的Python 3.6.1中

在bash终端输入这个解决了这个问题:

pip install certifi
/Applications/Python\ 3.6/Install\ Certificates.command
Run Code Online (Sandbox Code Playgroud)

  • 如果权限被拒绝,请尝试`sudo / Applications / Python \ 3.6 / Install \ Certificates.command`。 (2认同)

Bru*_*meu 37

在Windows上,Python不查看系统证书,它使用自己的位于?\lib\site-packages\certifi\cacert.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. 保存文件并享受请求!

  • Python 2.7.10中不存在`lib\site-packages\certifi\cacert.pem`.问题是关于`urllib2`而不是`requests` (5认同)
  • 到目前为止最好的解决方案,twitter API使用的DigiCert证书不在我的python的cacert.pem文件中.我在那里添加了VOILA! (2认同)
  • 在 Debian 上工作。作为记录,我系统上的文件路径是:`/usr/local/lib/python2.7/dist-packages/certifi-2015.09.06.2-py2.7.egg/certifi/cacert.pem`。谢谢! (2认同)

Cla*_*MBE 33

我的Mac OS X解决方案:

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

我发现这个安装程序比自制软件更好地更新新Python的链接和符号链接.

2)使用"./Install Certificates.command"安装新证书,该证书位于刷新的Python 3.6目录中

> cd "/Applications/Python 3.6/"
> sudo "./Install Certificates.command"
Run Code Online (Sandbox Code Playgroud)


Chr*_*row 27

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

PYTHONHTTPSVERIFY=0 
Run Code Online (Sandbox Code Playgroud)

请注意,这将禁用所有 HTTP验证,因此这是一个大锤方法,但如果不需要验证,它可能是一个有效的解决方案.

  • 我怀疑禁用所有python的所有HTTP验证对于处理验证中的一个错误来说有点过分.在很多情况下,默认情况下可能需要验证. (15认同)
  • 对我不起作用(debian8下的python 2.7). (7认同)
  • 另外,我在运行脚本之前直接在命令行窗口中设置变量,因此它不会禁用像@ someone-or-other那样害怕的所有检查,我也不建议这样做. (3认同)

Ali*_*Gol 20

我认为你有几种方法可以解决这个问题。我提到了下面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)
Run Code Online (Sandbox Code Playgroud)
  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')

Run Code Online (Sandbox Code Playgroud)
  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')
Run Code Online (Sandbox Code Playgroud)
  1. 或者如果您使用Linux计算机,则生成新证书并导出指向证书目录的环境变量可以修复该问题。
$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
Run Code Online (Sandbox Code Playgroud)
  1. 或者如果您使用Mac计算机,则生成新证书
$ cd "/Applications/$(python3 --version | awk '{print $2}'| awk  -F. '{print "Python " $1"."$2}')"
$ sudo "./Install Certificates.command"
Run Code Online (Sandbox Code Playgroud)


hBy*_*2Py 19

虽然我urllib.request.urlopenPython 3.4,3.5和3.6中使用过,但我遇到了类似的问题.(urllib2根据Python 2 urllib2文档页面的注释,这是Python 3等效的一部分.)

我的解决方案是pip install certifi安装certifi,其中包括:

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

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

import urllib.request as urlrq
resp = urlrq.urlopen('https://foo.com/bar/baz.html')
Run Code Online (Sandbox Code Playgroud)

我把它修改为:

import urllib.request as urlrq
import certifi
resp = urlrq.urlopen('https://foo.com/bar/baz.html', cafile=certifi.where())
Run Code Online (Sandbox Code Playgroud)

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


rit*_*iek 16

我在我的一台 Linux 机器上遇到了类似的问题。生成新证书并导出指向证书目录的环境变量为我修复了它:

$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
Run Code Online (Sandbox Code Playgroud)


Pro*_*tak 12

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
Run Code Online (Sandbox Code Playgroud)

取自这里https://gist.github.com/michaelrice/a6794a017e349fc65d01

  • 这是非常不安全的,因为它绕过了所有证书验证,使用风险自负,为了任何人的爱,不要在生产代码中使用它。 (2认同)

Ste*_*ich 10

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

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

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

urllib2.urlopen(req, cafile="verisign.pem")
Run Code Online (Sandbox Code Playgroud)


veg*_*iZe 8

$ cd $HOME
$ wget --quiet https://curl.haxx.se/ca/cacert.pem
$ export SSL_CERT_FILE=$HOME/cacert.pem
Run Code Online (Sandbox Code Playgroud)

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

  • 这看起来太简单了,我在最初的搜索中忽略了它。我现在正在踢自己。在 Ubuntu 上,为什么 Python 的 Certifi 使用单独的捆绑证书包而不是首先默认为系统证书包,这非常令人困惑。谢谢你拯救了我的一周。 (2认同)

小智 6

看一眼

/Applications/Python 3.6/Install Certificates.command
Run Code Online (Sandbox Code Playgroud)

您还可以转到ApplicationsFinder 中的文件夹并单击Certificates.command

  • 非常感谢!我刚刚转到“应用程序文件夹”,找到“Python”文件夹,然后单击“安装证书.command”文件。 (2认同)

Gan*_*ala 6

我在这里找到了这个

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

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
Run Code Online (Sandbox Code Playgroud)

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


Leo*_*Leo 6

Anaconda 的解决方案

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

  • 这是获得正确证书路径的方法:
import ssl
ssl.get_default_verify_paths()
Run Code Online (Sandbox Code Playgroud)

在我的系统上产生的

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')
Run Code Online (Sandbox Code Playgroud)

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

我已经设置了 conda 来使用我的代理,运行:

conda config --set ssl_verify <pathToYourFile>.crt
Run Code Online (Sandbox Code Playgroud)

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

ssl_verify: <pathToYourFile>.crt
Run Code Online (Sandbox Code Playgroud)

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

进一步的警告

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

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

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

import ssl
ssl.get_default_verify_paths()
Run Code Online (Sandbox Code Playgroud)


Web*_*Dev 6

由于 Linux 上的包中缺少中间证书,也可能会出现 SSL: CERTIFICATE_VERIFY_FAILED 错误ca-certificates。例如,在我的例子中,中间证书“ DigiCert SHA2 Secure Server CA ”在包中丢失ca-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
Run Code Online (Sandbox Code Playgroud)

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


cao*_*aot 5

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

  • 我在 mac 上的 2.7.12 上遇到了它,使用 urllib2 库,虽然使用 requets 库似乎很好 (3认同)

cor*_*ber 5

我需要添加另一个答案,因为就像Craig Glennie一样,由于网络上有很多帖子提到了这个问题,所以我大肆追赶。

我正在使用MacPorts,最初我认为是Python问题实际上是MacPorts问题:它没有在安装openssl时安装根证书。如本博客文章port install curl-ca-bundle所述,解决方案是。


ber*_*iey 5

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

  • 在 Mac 上,Apple 正在放弃 OpenSSL
  • Python 现在使用它自己的一组 CA 根证书
  • 二进制 Python 安装提供了一个脚本来安装 Python 需要的 CA 根证书(“/Applications/Python 3.6/Install Certificates.command”)
  • 阅读“/Applications/Python 3.6/ReadMe.rtf”了解详情

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

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 \
  /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/cert.pem
Run Code Online (Sandbox Code Playgroud)

如果那仍然失败了。然后也重新/安装 OpenSSL。

port install openssl
Run Code Online (Sandbox Code Playgroud)