我正在编写一个简单的脚本,涉及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

当前回答

这与@rafael-almeida的回答类似,但我想指出的是,对于2.11+的请求,没有3个值可以验证,实际上有4个:

True:根据请求的内部可信ca进行验证。 False:完全跳过证书验证。(不推荐) CA_BUNDLE文件的路径。请求将使用它来验证服务器的证书。 包含公共证书文件的路径。请求将使用它来验证服务器的证书。

我剩下的答案是关于#4,如何使用包含证书的目录来验证:

获取所需的公共证书,并将它们放在一个目录中。

严格地说,您可能“应该”使用带外方法获取证书,但您也可以使用任何浏览器下载它们。

如果服务器使用证书链,请确保获取链中的每个证书。

根据请求文档,包含证书的目录必须首先使用“rehash”实用程序(openssl rehash)进行处理。

(这需要openssl 1.1.1+,并且不是所有的Windows openssl实现都支持rehash。如果openssl rehash对你不起作用,你可以尝试在https://github.com/ruby/openssl/blob/master/sample/c_rehash.rb上运行rehash ruby脚本,尽管我还没有尝试过。)

我在让请求识别我的证书时遇到了一些麻烦,但是在我使用openssl x509 -outform PEM命令将证书转换为Base64 . PEM格式后,一切都完美地工作了。

你也可以只做惰性重哈希:

try:
    # As long as the certificates in the certs directory are in the OS's certificate store, `verify=True` is fine.
    return requests.get(url, auth=auth, verify=True)
except requests.exceptions.SSLError:
    subprocess.run(f"openssl rehash -compat -v my_certs_dir", shell=True, check=True)
    return requests.get(url, auth=auth, verify="my_certs_dir")

其他回答

这与@rafael-almeida的回答类似,但我想指出的是,对于2.11+的请求,没有3个值可以验证,实际上有4个:

True:根据请求的内部可信ca进行验证。 False:完全跳过证书验证。(不推荐) CA_BUNDLE文件的路径。请求将使用它来验证服务器的证书。 包含公共证书文件的路径。请求将使用它来验证服务器的证书。

我剩下的答案是关于#4,如何使用包含证书的目录来验证:

获取所需的公共证书,并将它们放在一个目录中。

严格地说,您可能“应该”使用带外方法获取证书,但您也可以使用任何浏览器下载它们。

如果服务器使用证书链,请确保获取链中的每个证书。

根据请求文档,包含证书的目录必须首先使用“rehash”实用程序(openssl rehash)进行处理。

(这需要openssl 1.1.1+,并且不是所有的Windows openssl实现都支持rehash。如果openssl rehash对你不起作用,你可以尝试在https://github.com/ruby/openssl/blob/master/sample/c_rehash.rb上运行rehash ruby脚本,尽管我还没有尝试过。)

我在让请求识别我的证书时遇到了一些麻烦,但是在我使用openssl x509 -outform PEM命令将证书转换为Base64 . PEM格式后,一切都完美地工作了。

你也可以只做惰性重哈希:

try:
    # As long as the certificates in the certs directory are in the OS's certificate store, `verify=True` is fine.
    return requests.get(url, auth=auth, verify=True)
except requests.exceptions.SSLError:
    subprocess.run(f"openssl rehash -compat -v my_certs_dir", shell=True, check=True)
    return requests.get(url, auth=auth, verify="my_certs_dir")

我遇到了类似或相同的认证验证问题。我读到过小于1.0.2的OpenSSL版本,请求所依赖的版本有时会在验证强证书时遇到麻烦(见这里)。CentOS 7似乎使用了1.0.1e,这似乎有问题。

我不确定如何在CentOS上解决这个问题,所以我决定允许较弱的1024bit CA证书。

import certifi # This should be already installed as a dependency of 'requests'
requests.get("https://example.com", verify=certifi.old_where())

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

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

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

如果你有一个依赖于请求的库,你不能修改验证路径(比如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')";

我不得不从Python 3.4.0升级到3.4.6

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