Python请求引发SSLError
我正在研究一个涉及CAS,jspring安全检查,redirect等的简单脚本。我想使用Kenneth Reitz的python请求,因为这是一个伟大的工作! 但是,CAS需要通过SSL进行validation,所以我必须先经过这一步。 我不知道Python要求的是什么? 这个SSL证书应该放在哪里?
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一样, 最快的解决方法是设置verify=False
。
请注意,这将导致证书不被validation。 这会使您的应用程序面临安全风险,例如中间人攻击。
当然,应用判断。 正如评论中提到的那样,对于快速/不重要的应用程序/脚本来说,这可能是可以接受的, 但实际上不应该用于生产软件 。
如果只是跳过证书检查在您的特定上下文中是不可接受的,请考虑以下选项,最好的select是将verify
参数设置为证书的.pem
文件path的string(您应该获得某种安全的手段)。
因此,从版本2.0开始, verify
参数接受下列值及其各自的语义:
-
True
:使证书根据图书馆自己的可信证书颁发机构进行validation(注意:可以通过Certifi库(从Requests: Certifi – Trust Database for Humans )中提取RC的信任数据库来查看哪些根证书请求使用。 -
False
: 完全绕过证书validation。 - 请求用于validation证书的CA_BUNDLE文件的path。
来源: 请求 – SSL证书validation
也请看看同一链接上的cert
参数。
从SSLvalidation请求文档 :
请求可以validationHTTPS请求的SSL证书,就像Web浏览器一样。 要检查主机的SSL证书,可以使用verify参数:
>>> requests.get('https://kennethreitz.com', verify=True)
如果您不想validation您的SSL证书,请将verify=False
要使用的CA文件的名称可以通过verify
:
cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem r = requests.get(url, verify=cafile)
如果您使用verify=True
那么requests
将使用自己的CA集合,该集合可能没有签名了您的服务器证书的CA.
我遇到同样的问题和ssl证书validation失败的问题,当使用aws boto3,通过审查boto3代码,我发现REQUESTS_CA_BUNDLE没有设置,所以我通过手动设置它解决了这两个问题:
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,我猜想在~/.bashrc
设置REQUESTS_CA_BUNDLE可以解决这个问题(未经testing,因为我的aws-cli没有这个工作)。
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt export REQUESTS_CA_BUNDLE
$ pip install -U requests[security]
- testingPython 2.7.6 @ Ubuntu 14.04.4 LTS
- testingPython 2.7.5 @ MacOSX 10.9.5(小牛)
当这个问题被打开(2012-05)时,请求版本是0.13.1。 在版本2.4.1(2014-09)引入了“安全”附加function,使用certifi
包(如果可用)。
现在(2016-09)的主版本是2.11.1, 没有 verify=False
用作requests.get(url, verify=False)
,如果与requests[security]
额外安装。
我使用gspread面对同样的问题,这些命令适用于我:
sudo pip uninstall -y certifi sudo pip install certifi==2015.04.28
我find了解决类似问题的具体方法。 这个想法指向存储在系统中的cacert文件,并被另一个基于ssl的应用程序使用。
在Debian中(我不确定是否在其他发行版中也是如此)证书文件(.pem)存储在/etc/ssl/certs/
所以,这是我工作的代码:
import requests verify='/etc/ssl/certs/cacert.org.pem' response = requests.get('https://lists.cacert.org', verify=verify)
为了猜测什么pem
文件select,我浏览到URL并检查哪个证书颁发机构(CA)已经生成证书。
编辑:如果你不能编辑代码(因为你正在运行第三个应用程序),你可以尝试直接添加到/usr/local/lib/python2.7/dist-packages/requests/cacert.pem
(例如复制它到文件的结尾)。
如果你有一个依靠requests
的库,你不能修改validationpath(就像使用pyvmomi
),那么你将不得不find与请求捆绑在一起的cacert.pem
,并在那里附加你的CA. 这是一个通用的方法来findcacert.pem
位置:
视窗
C:\>python -c "import requests; print requests.certs.where()" c:\Python27\lib\site-packages\requests-2.8.1-py2.7.egg\requests\cacert.pem
Linux的
# (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与请求绑定在一起真的很烦人……特别是你似乎并没有首先使用系统ca store,而且这种情况在任何地方都没有logging。
更新
在使用库的情况下,无法控制ca-bundle位置的情况下,您还可以明确地将ca-bundle位置设置为您的主机范围的ca-bundle:
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com';)"
如果你不打扰证书,只需使用verify=False
。
import requests url = "Write your url here" returnResponse = requests.get(url, verify=False)
如果您想删除警告,请使用下面的代码。
import urllib3 urllib3.disable_warnings()
并通过request.get
或post
方法verify=False
我遇到了同样的问题。 事实certificate,我没有在我的服务器上安装中间证书(只是将其附加到证书的底部,如下所示)。
https://www.digicert.com/ssl-support/pem-ssl-creation.htm
确保你已经安装了ca-certificates包:
sudo apt-get install ca-certificates
更新时间也可以解决这个问题:
sudo apt-get install ntpdate sudo ntpdate -u ntp.ubuntu.com
如果您使用的是自签名证书,则可能需要手动将其添加到系统中。
经过几个小时的debugging,我只能使用下列软件包来实现这个function:
requests[security]==2.7.0 # not 2.18.1 cryptography==1.9 # not 2.0
使用OpenSSL 1.0.2g 1 Mar 2016
没有这些包verify=False
不起作用。
我希望这可以帮助别人。
我打了小时这个问题。
我试图更新请求。 然后我更新了certifi。 我指出validationcertifi.where()(代码默认这是默认情况下)。 没有工作。
最后,我更新了我的Python版本到Python 2.7.11。 我在Python 2.7.5上,它与证书的validation方式有一些不兼容的地方。 一旦我更新Python(和一些其他的依赖),它开始工作。
目前在v2.6.2到v2.12.4(ATOW)中的请求模块中存在引起此错误的问题: https : //github.com/kennethreitz/requests/issues/2573
解决此问题的方法是添加以下行: requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
如果从另一个包中调用请求,则添加选项是不可行的。 在这种情况下向cacert bundle添加证书是直接的path,例如,我必须添加“StartCom Class 1主中级服务器CA”,为此我将根证书下载到StartComClass1.pem中。 鉴于我的virtualenv被命名为caldav,我添加了证书:
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
其中一个可能就够了,我没有检查
正如@Rafael Almeida所提到的,您遇到的问题是由不可信的SSL证书引起的。 在我的情况下,SSL证书不受我的服务器的信任。 为了解决这个问题而不影响安全性,我下载了证书 ,并将其安装在服务器上(只需双击.crt文件,然后安装证书…)。
我有一个类似或相同的authenticationvalidation问题。 我读了OpenSSL版本低于1.0.2,哪些请求取决于有时有困难的validation强证书(见这里 )。 CentOS 7似乎使用1.0.1e似乎有问题。
我不确定如何在CentOS上解决这个问题,所以我决定允许较弱的1024位CA证书。
import certifi # This should be already installed as a dependency of 'requests' requests.get("https://example.com", verify=certifi.old_where())
如果请求调用被隐藏在代码深处,并且您不想安装服务器证书,那么仅仅为了debugging目的 ,可能需要monkeypatch请求:
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('Pathched requests: SSL verification disabled!')
切勿在生产中使用!