Python Requests throwing SSLError
我正在编写一个简单的脚本,它涉及到CA、jSpring安全检查、重定向等。我想使用Kenneth Reitz的python请求,因为这是一项伟大的工作!但是,CA需要通过SSL进行验证,因此我必须先通过该步骤。我不知道python需要什么请求?这个SSL证书应该放在哪里?
1 2 3 4 5 6 7 8 9 10 | Traceback (most recent call last): File"./test.py", line 24, in <module> response = requests.get(url1, headers=headers) File"build/bdist.linux-x86_64/egg/requests/api.py", line 52, in get File"build/bdist.linux-x86_64/egg/requests/api.py", line 40, in request File"build/bdist.linux-x86_64/egg/requests/sessions.py", line 209, in request File"build/bdist.linux-x86_64/egg/requests/models.py", line 624, in send File"build/bdist.linux-x86_64/egg/requests/models.py", line 300, in _build_response File"build/bdist.linux-x86_64/egg/requests/models.py", line 611, in send requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed |
您遇到的问题是由不受信任的SSL证书引起的。
就像前面评论中提到的@dirk一样,最快的解决方法是设置
1 | requests.get('https://example.com', verify=False) |
号
请注意,这将导致证书无法验证。这将使您的应用程序面临安全风险,例如中间人攻击。
当然,运用判断。正如注释中提到的,对于快速/一次性应用程序/脚本,这可能是可以接受的,但实际上不应该转到生产软件。
如果在您的特定上下文中不接受跳过证书检查,请考虑以下选项,您的最佳选择是将
因此,从2.0版开始,
True :使证书根据库自己的受信任证书颁发机构进行验证(注意:您可以通过certifi库查看请求使用的根证书,该库是从请求中提取的rcs的信任数据库:certifi-人类信任数据库)。False :完全绕过证书验证。- 用于验证证书的请求的CA捆绑文件的路径。
来源:请求-SSL证书验证
还可以查看同一链接上的
来自有关SSL验证的请求文档:
Requests can verify SSL certificates for HTTPS requests, just like a web browser. To check a host’s SSL certificate, you can use the verify argument:
号
1 | >>> requests.get('https://kennethreitz.com', verify=True) |
如果您不想验证您的SSL证书,请使EDOCX1[0]
您可以通过
1 2 | cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem r = requests.get(url, verify=cafile) |
如果您使用
江户十一〔四〕号
- 在python 2.7.6@ubuntu 14.04.4 LTS上测试
- 在python 2.7.5@macosx 10.9.5上测试(Mavericks)
打开此问题(2012-05)时,请求版本为0.13.1。在版本2.4.1(2014-09)中,引入了"安全"附加程序,如果可用,则使用
现在(2016-09)主版本是2.11.1,没有
我在使用aws boto3时遇到了相同的问题和ssl证书验证失败的问题,通过查看boto3代码,我发现
1 2 3 4 5 6 7 8 9 | from boto3.session import Session import os # debian os.environ['REQUESTS_CA_BUNDLE'] = os.path.join( '/etc/ssl/certs/', 'ca-certificates.crt') # centos # 'ca-bundle.crt') |
对于aws cli,我想在
1 2 | REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt export REQUESTS_CA_BUNDLE |
。
如果您有一个依赖于
窗户
1 2 3 4 | C:\>python -c"import requests; print requests.certs.where()" c:\Python27\lib\site-packages equests-2.8.1-py2.7.egg equests\cacert.pem |
Linux
1 2 3 4 5 6 7 | # (py2.7.5,requests 2.7.0, verify not enforced) root@host:~/# python -c"import requests; print requests.certs.where()" /usr/lib/python2.7/dist-packages/certifi/cacert.pem # (py2.7.10, verify enforced) root@host:~/# python -c"import requests; print requests.certs.where()" /usr/local/lib/python2.7/dist-packages/requests/cacert.pem |
号
顺便说一下@requests devs,把你自己的cacerts和request捆绑在一起真的,真的很烦人…尤其是,您似乎没有首先使用系统CA存储,而且这在任何地方都没有记录。
更新
在使用库且无法控制CA束位置的情况下,还可以显式将CA束位置设置为主机范围的CA束:
1 | REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c"import requests; requests.get('https://somesite.com';)" |
我使用gspread也面临同样的问题,这些命令对我很有用:
1 2 | sudo pip uninstall -y certifi sudo pip install certifi==2015.04.28 |
号
如果要删除警告,请使用下面的代码。
1 2 3 | import urllib3 urllib3.disable_warnings() |
。
用
我找到了解决类似问题的具体方法。其思想是指向存储在系统中并由另一个基于SSL的应用程序使用的cacert文件。
在Debian中(我不确定在其他发行版中是否相同),证书文件(.pem)存储在
1 2 3 | import requests verify='/etc/ssl/certs/cacert.org.pem' response = requests.get('https://lists.cacert.org', verify=verify) |
。
为了猜测
编辑:如果您不能编辑代码(因为您正在运行第三个应用程序),您可以尝试将
如果您不关心证书,只需使用
1 2 3 4 5 | import requests url ="Write your url here" returnResponse = requests.get(url, verify=False) |
。
经过数小时的调试后,我只能使用以下包使其正常工作:
1 2 | requests[security]==2.7.0 # not 2.18.1 cryptography==1.9 # not 2.0 |
使用
没有这些包,
我希望这能帮助别人。
我也遇到了同样的问题。结果发现我没有在服务器上安装中间证书(只需将其附加到证书的底部,如下所示)。
网址:https://www.digicert.com/ssl-support/pem-ssl-creation.htm
确保已安装CA证书包:
1 | sudo apt-get install ca-certificates |
更新时间也可以解决此问题:
1 2 | sudo apt-get install ntpdate sudo ntpdate -u ntp.ubuntu.com |
。
如果您使用的是自签名证书,则可能需要手动将其添加到系统中。
我和这个问题打了几个小时。
我试图更新请求。然后我更新了certifi。我将verify指向certifi.where()(代码默认情况下会这样做)。什么都没用。
最后,我将python的版本更新为python 2.7.11。我使用的是Python2.7.5,它与验证证书的方式有些不兼容。一旦我更新了python(以及其他一些依赖项),它就开始工作了。
请求模块中当前存在导致此错误的问题,出现在v2.6.2到v2.12.4(ATOW)中:https://github.com/kennethreitz/requests/issues/2573
解决此问题的方法是添加以下行:
如果请求调用隐藏在代码的某个深度,并且您不想安装服务器证书,那么,仅出于调试目的,可以对monkeypatch请求进行以下操作:
1 2 3 4 5 6 7 8 9 10 11 | import requests.api import warnings def requestspatch(method, url, **kwargs): kwargs['verify'] = False return _origcall(method, url, **kwargs) _origcall = requests.api.request requests.api.request = requestspatch warnings.warn('Patched requests: SSL verification disabled!') |
。
不要在生产中使用!
正如@rafael almeida所提到的,您遇到的问题是由不受信任的SSL证书引起的。在我的例子中,我的服务器不信任SSL证书。为了在不影响安全性的情况下解决这个问题,我下载了证书,并将其安装在服务器上(只需双击.crt文件,然后安装证书…)。
我想去参加聚会已经太迟了,但我想为像我这样的流浪汉们贴上修正的标签!所以下面的内容在python 3.7.x上对我有所帮助
在终端中键入以下内容
1 | pip install --upgrade certifi # hold your breath.. |
再次尝试运行您的脚本/请求,看看它是否有效(我确信它还没有被修复!)。如果它不起作用,则尝试直接在终端中运行以下命令
1 | open /Applications/Python\ 3.6/Install\ Certificates.command # please replace 3.6 here with your suitable python version |
。
在我的例子中,原因是相当微不足道的。
我知道ssl验证直到几天前才起作用,实际上是在另一台机器上工作。
我的下一步是比较验证工作的机器和不工作的机器之间的证书内容和大小。
这很快导致我确定"不正确"工作机器上的证书不好,一旦我用"良好"证书替换它,一切都很好。
我遇到了类似或相同的认证验证问题。我读到OpenSSL版本低于1.0.2,请求依赖于它,有时验证强证书时会遇到困难(请参见此处)。Centos7似乎使用了1.0.1e,这似乎有问题。
我不知道如何在CentOS上解决这个问题,所以我决定允许更弱的1024位CA证书。
1 2 | import certifi # This should be already installed as a dependency of 'requests' requests.get("https://example.com", verify=certifi.old_where()) |
。
如果从另一个包调用请求,则添加选项是不可行的。在这种情况下,向ca cert包中添加证书是一条直线路径,例如,我必须添加"startcom class 1 primary intermediate server ca",为此,我将根证书下载到startcom class 1.pem中。鉴于我的virtualenv名为caldav,我添加了证书:
1 2 | cat StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/pip/_vendor/requests/cacert.pem cat temp/StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/requests/cacert.pem |
其中一个可能足够了,我没有检查
我必须从python 3.4.0升级到3.4.6
1 2 3 | pyenv virtualenv 3.4.6 myvenv pyenv activate myvenv pip install -r requirements.txt |
。