我得到以下错误:

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。我怎样才能让它绕过验证呢?


当前回答

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

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

其他回答

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

拷贝CA.crt到/etc/pki/ca-trust/source/anchors/ update-ca-trust force-enable update-ca-trust提取

我认为你有几种方法可以解决这个问题。我提到了以下5种方法:

你可以为每个请求定义上下文,并在每个请求上传递上下文,如下所示:

import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)

或在环境中设置证书文件。

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')

创建默认的https上下文方法:

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')

如果您使用Linux机器,生成新的证书并导出指向证书目录的环境变量,则可以修复该问题。

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

或如果您使用Mac机器,生成新的证书

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

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

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

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

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

如果证书是通过Let's encrypt颁发的,请确保在客户机上的中间证书存储中删除过期的DST根CA X3颁发的R3证书。

进口的要求 Response =请求。Get("你想要访问的url/api ", verify=" SSL证书的路径")

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

当然,SSL证书是必要的,但当您处于公司防火墙之后,那么公开可用的证书可能就没有帮助了。您可能需要联系您公司的IT部门来获得证书,因为每个公司都使用从他们签约服务的安全提供商那里获得的特殊证书。然后把它放到一个文件夹中并把路径作为验证参数传递给那个文件夹。

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

在我的例子中,我把证书放在下面的路径中,它像魔术一样起作用。

C:\Program Files\Common文件\ssl

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