我正在编写一个简单的脚本,涉及CAS、jspring安全检查、重定向等。我想使用Kenneth Reitz的python请求,因为它是一个伟大的作品!然而,CAS需要通过SSL进行验证,所以我必须先通过这一步。我不知道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

当前回答

如果你有一个依赖于请求的库,你不能修改验证路径(比如pyvmomi),那么你必须找到cacert。. pem和请求捆绑在一起,并在那里追加您的CA。下面是查找cacert的通用方法。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和request捆绑在一起真的很讨厌…特别是事实是,您似乎没有首先使用系统ca存储,这是没有记录在任何地方。

更新

在使用库且无法控制ca-bundle位置的情况下,你也可以显式地将ca-bundle位置设置为主机范围内的ca-bundle:

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com')";

其他回答

如果从另一个包调用请求,则添加选项是不可行的。在这种情况下,将证书添加到cacert包是直接的路径,例如,我必须添加“StartComClass1 Primary Intermediate Server 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

其中一个可能就够了,我没有检查

我找到了一个解决类似问题的具体方法。这个想法是指向存储在系统中的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文件的选择,我已经浏览到url并检查哪个证书颁发机构(CA)生成了证书。

编辑:如果你不能编辑代码(因为你正在运行第三个应用程序),你可以尝试直接将pem证书添加到/usr/local/lib/python2.7/dist-packages/requests/cacert。Pem(例如将其复制到文件的末尾)。

有些服务器没有Letsencrypt的可信根证书。

例如,假设下面的url指向的服务器受到Letsencrypt SSL的保护。

requests.post(url, json=data)

此请求可能使用[SSL: CERTIFICATE_VERIFY_FAILED]失败,因为请求服务器没有Letsencrypt的根证书。

当发生这种情况时,请从下面的链接下载活动自签名的“pem”证书。

https://letsencrypt.org/certificates/。(在撰写本文时,ISRG根X1处于活动状态)

现在,在verify参数中使用它,如下所示。

requests.post(url, json=data, verify='path-to/isrgrootx1.pem')

我不得不从Python 3.4.0升级到3.4.6

pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt

我为这个问题奋斗了好几个小时。

我尝试更新请求。然后我更新了证书。我将verify指向certificate .where()(代码在默认情况下这样做)。毫无效果。

最后,我将python版本更新到python 2.7.11。我使用的是Python 2.7.5,它与证书验证的方式有一些不兼容。一旦我更新了Python(以及一些其他依赖项),它就开始工作了。