urllib和" SSL:CERTIFICATE_VERIFY_FAILED"错误

时间:2015-01-08 08:14:34

标签: python python-2.7 ssl ssl-certificate urllib

我收到以下错误:

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。如何绕过验证?

40 个答案:

答案 0 :(得分:282)

这不是您特定问题的解决方案,但我将其放在此处是因为此主题是“SSL:CERTIFICATE_VERIFY_FAILED”的Google搜索结果,并且它引导我进行疯狂的追逐。

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

找到它

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

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

答案 1 :(得分:236)

如果只是想要绕过验证,您可以创建新的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中所述:

  

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

如果您想阅读一篇关于为什么不在软件you can find it here验证证书不好的论文!

答案 2 :(得分:53)

扩展Craig Glennie的回答:

Mac OS Sierra上的Python 3.6.1中的

在bash终端中输入此内容解决了问题:

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

答案 3 :(得分:28)

我的Mac OS X解决方案:

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

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

2)使用&#34; ./安装Certificates.command&#34;安装新证书。它位于刷新的Python 3.6目录中

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

答案 4 :(得分:27)

在Windows上,Python不查看系统证书,它使用自己的?\lib\site-packages\certifi\cacert.pem

解决问题的方法:

  1. 将域验证证书下载为* .crt或* pem file
  2. 在编辑器中打开文件并将其内容复制到剪贴板
  3. 找到您的cacert.pem位置:from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)
  4. 编辑cacert.pem文件并将您的域验证证书粘贴到文件末尾。
  5. 保存文件并享受请求!

答案 5 :(得分:26)

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

PYTHONHTTPSVERIFY=0 

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

答案 6 :(得分:15)

虽然我在 Python 3.4,3.5和3.6 中使用urllib.request.urlopen,但我遇到了类似的问题。 (这是Python 3等效于urllib2的一部分,根据Python 2&#39; s urllib2 documentation page的注释。)

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

  

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

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

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

我将其修改为:

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

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

答案 7 :(得分: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

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

答案 8 :(得分:9)

就像我在评论中写的一样,这个问题可能与this SO answer有关。

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

您可以尝试获取Verisign Class 3 Public Primary Certification Authority的遗失证书,然后根据Python documentation使用cafile选项:

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

答案 9 :(得分:6)

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

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

答案 10 :(得分:4)

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

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

答案 11 :(得分:4)

对于 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

答案 12 :(得分:3)

我需要添加另一个答案,因为就像克雷格·格伦尼一样,由于网上有很多关于这个问题的帖子,我进行了疯狂的追逐。

我正在使用MacPorts,而我最初认为是Python问题实际上是一个MacPorts问题:它没有安装根证书及其openssl的安装。解决方案是port install curl-ca-bundle,如this blog post中所述。

答案 13 :(得分:3)

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

答案 14 :(得分:3)

我半信半疑,因为我有同样的问题,除了在我的情况下,我打的URL是有效的,证书是有效的。什么是无效的是我的网络连接。我没有将代理详细信息添加到浏览器中(在本例中为IE)。这阻止了验证过程的正确发生 在代理细节中添加了我的python然后非常高兴。

答案 15 :(得分:2)

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

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

对我来说,脚本不起作用,所有那些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

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

port install openssl

答案 16 :(得分:2)

带有centOS 7的Amazon EC2上的Python 2.7

我必须将env变量SSL_CERT_DIR设置为指向位于ca-bundle的{​​{1}}

答案 17 :(得分:2)

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

wget

此后,您可以使用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 再次测试您的URL,也可以使用python wget包进行测试。有关更多详细信息,请参阅:https://bugs.launchpad.net/ubuntu/+source/ca-certificates/+bug/1795242

答案 18 :(得分:2)

和你一样,我在旧的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. 没问题
  3. Homebrew tool提供的问题:&#34; brew install python&#34;,版本位于/ usr / local / bin。

  4. Certificate verification and OpenSSL [CHANGED for Python 2.7.9]中的一个名为/Applications/Python 2.7/ReadMe.rtf的章节解释了许多细节的问题。

    所以,检查,下载并在你的PATH中输入正确版本的python。

答案 19 :(得分:1)

尝试

  

pip install --trusted-host pypi.python.org packagename

它对我有用。

答案 20 :(得分:1)

看看

/ Applications / Python 3.6 /安装Certificates.command

您也可以访问Aplications并点击Certificates.command

答案 21 :(得分:1)

在某些情况下,您不能使用不安全的连接或无法将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)

答案 22 :(得分:0)

你可以试试这个

<块引用>

pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org

答案 23 :(得分:0)

我在Python 2.7.9中遇到了这个问题

这是我所做的:

  • 未安装的Python 2.7.9
  • 已删除c:\ Python27文件夹
  • 下载了Python 2.7.18,这是今天最新的Python 2.7版本。
  • 重新运行我的应用程序
  • 它奏效了!

不再有任何“ [[CERTIFICATE_VERIFY_FAILED]]证书验证失败(_ssl.c:581)”错误。

答案 24 :(得分:0)

导入请求
response = requests.get("url/api that you want to hit", verify="ssl 证书的路径")

对我来说,问题是上述答案都没有完全帮助我,但给了我正确的方向。

当然,需要 SSL 证书,但是当您位于公司的防火墙之后时,公开可用的证书可能无济于事p。您可能需要联系您公司的 IT 部门以获取证书,因为每家公司都使用与他们签订服务合同的安全提供商提供的特殊证书。并将其放在一个文件夹中,并将该文件夹的路径作为参数传递给验证参数

对我来说,即使在尝试了上述所有解决方案并使用了错误的证书后,我也无法使其正常工作。所以请记住,那些在公司防火墙后面的人要获得正确的证书。它可以决定请求调用的成功与否。

在我的情况下,我将证书放在以下路径中,它就像魔术一样工作。

C:\Program Files\Common Files\ssl

您也可以参考https://2.python-requests.org/en/master/user/advanced/#id3,其中讨论了 ssl 验证

答案 25 :(得分:0)

如果您要处理私有证书,例如您的组织自己的CA根目录和中间链部分,那么最好将证书添加到ca文件,即。 cacert.pem,而不是绕过整个安全设备(verify = False)。以下代码可让您同时使用2.7+和3 +

考虑添加整个证书链,当然,您只需要这样做一次。

import certifi

cafile=certifi.where() # cacert file
with open ('rootca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)
with open ('interca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)
with open ('issueca.pem','rb') as infile:
    customca=infile.read()
    with open(cafile,'ab') as outfile:
        outfile.write(customca)

那么这应该可以帮助您

import requests
response = requests.request("GET", 'https://yoursecuresite.com',  data = {})
print(response.text.encode('utf8'))

希望这会有所帮助

答案 26 :(得分:0)

这里已经有很多答案了,但是我们在一个非常具体的案例中遇到了这个问题,并且花了很多时间进行调查,因此又增加了一个答案。我们在以下情况下看到了它:

  • 在debian-stretch-slim docker容器中
  • 默认Python 3.5.3 easy_install3
  • 对于在我们的Kubernetes集群中使用cert-manager注册的LetsEncrypt证书

pip3openssl命令行都能够验证证书,而easy_install3能够成功验证其他LetsEncrypt证书。

解决方法是从源代码构建最新的Python(当时为3.7.3)。说明here详细且易于遵循。

答案 27 :(得分:0)

另一个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

答案 28 :(得分:0)

在我的情况下,我遇到此错误是因为requestsurllib3版本不兼容,在安装过程中出现以下错误:

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 :(得分:0)

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根本不存在。

  • 下面的命令提供的路径是 WRONG 路径

from requests.utils import DEFAULT_CA_BUNDLE_PATH
DEFAULT_CA_BUNDLE_PATH

答案 30 :(得分:0)

对于Linux Python3.6,这对我有用。

从命令行安装pyopenssl和certifi

sudo pip3 install -U pyopenssl
sudo pip3 install certifi

在我的python3脚本中,添加了verify ='/ usr / lib / python3.6 / site-packages / certifi / cacert.pem',如下所示:

import requests
from requests.auth import HTTPBasicAuth
import certifi

auth = HTTPBasicAuth('username', 'password')
body = {}

r = requests.post(url='https://your_url.com', data=body, auth=auth, verify='/usr/lib/python3.6/site-packages/certifi/cacert.pem')

答案 31 :(得分:0)

我在here上找到了这个

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

getRecord

此代码取消了验证,因此未验证ssl认证。

答案 32 :(得分:0)

在Mac上安装certifi解决了我的问题:

pip install certifi

答案 33 :(得分:0)

对于使用mechanize遇到此问题的任何人,以下是如何将相同技术应用于机械化浏览器实例的方法:

br = mechanize.Browser()
context = ssl._create_unverified_context()
br.set_ca_data(context=context)

答案 34 :(得分:0)

在python 2.7中,最后在文件C:\ Python27 \ lib \ site-packages \ certifi \ cacert.pem中添加了受信任的根CA详细信息

之后,我确实运行了(使用管理员权限) pip install --trusted-host pypi.python.org --trusted-host pypi.org --trusted-host files.pythonhosted.org packageName

答案 35 :(得分:0)

我通过关闭Fiddler(HTTP调试代理)检查是否启用了代理并再次尝试解决了这个问题。

答案 36 :(得分:0)

使用PyOpenSSL安装pip为我工作(无需转换为PEM):

pip install PyOpenSSL

答案 37 :(得分:0)

安装nltk的步骤(我已经在MAC OS X中安装了python3(3.6.2)

sudo easy_install pip

使用ignore installed选项忽略卸载以前的六个版本,否则,卸载时会出错并且不会向前移动

sudo pip3 install -U nltk --ignore-installed six

检查pip和python的安装,使用&#39; 3&#39;版本

which python python2 python3
which pip pip2 pip3

检查是否已安装NLTK

python3
import nltk
nltk.__path__
['/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/nltk']

在安装示例书之前安装SSL证书,否则我们将在安装示例时出现证书错误

/Applications/Python\ 3.6/Install\ Certificates.command
python3 -m nltk.downloader book

完成了nltk和nltk_ata的成功安装,用于书籍示例

答案 38 :(得分:0)

如果您在vCenter 6上,则应将vCenter的vmware证书颁发机构证书添加到操作系统的受信任CA列表中。要下载您的证书,请执行以下操作

  1. 打开网络浏览器。
  2. 导航至https://
  3. 在右下角,单击“下载受信任的根CA”链接
  4. 在Fedora上

    1. 解压缩并将扩展名从.0更改为.cer
    2. 将其复制到/ etc / pki / ca-trust / source / anchors /
    3. 运行update-ca-trust命令。
    4. 链接:

      1. https://virtualizationreview.com/articles/2015/04/02/install-root-self-signed-certificate-vcenter-6.aspx?m=1
      2. http://forums.fedoraforum.org/showthread.php?t=293856

答案 39 :(得分:-6)

ln -s /usr/local/share/certs/ca-root-nss.crt /etc/ssl/cert.pem

FreeBSD 10.1