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

当前回答

对我来说,原因相当微不足道。

直到几天前,我才知道SSL验证工作正常,实际上是在另一台机器上工作。

我的下一步是比较正在进行验证的机器和没有进行验证的机器之间的证书内容和大小。

这很快导致我确定在“不正确”工作的机器上的证书并不好,一旦我用“良好”证书替换它,一切都很好。

其他回答

正如@Rafael Almeida所提到的,您遇到的问题是由不受信任的SSL证书引起的。在我的例子中,我的服务器不信任SSL证书。为了在不影响安全性的情况下解决这个问题,我下载了证书,并将其安装到服务器上(只需双击.crt文件,然后安装证书…)。

如果要删除警告,请使用下面的代码。

import urllib3

urllib3.disable_warnings()

and verify=False与请求。Get或post方法

正如其他人指出的那样,这个问题“是由不受信任的SSL证书引起的”。我的答案是基于评分最高的答案和这个答案。

您可以使用curl测试证书:

curl -vvI https://example.com

如果一个错误返回,你有3个选项:

为了快速修复,您可以不验证证书:

requests.get('https://example.com', verify=False)

将路径传递给CA_BUNDLE文件或包含受信任ca证书的目录:

requests.get('https://example.com', verify='/path/to/certfile')

如果您有权访问,请修复web服务器证书。

我的问题在于我只使用了我站点的证书,而不是中间证书(也就是链证书)。

如果你正在使用Let's Encrypt,你应该使用全链。Pem文件,而不是cert.pem。

我找到了一个解决问题的答案:

import ssl
import certifi
import urllib.request

url = "https://www.google.com/"
html = urllib.request.urlopen(url, context=ssl.create_default_context(cafile=certifi.where()))

但我不知道它是干什么用的。

这与@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")