【问题标题】:Python call to request() to SSL site not pointing to netrcPython 调用 request() 到 SSL 站点不指向 netrc
【发布时间】:2020-03-14 06:08:13
【问题描述】:

用 Anaconda3 测试一段简单的代码:

import requests as req

resp = req.get("https://api.github.com")
print(resp.text)

我得到这个错误:

SSLError: HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')])")))

使用调试器跟踪调用,问题似乎出现在 requests.utils 中的get_netrc_auth() 中。这里,这段代码用于获取 netrc 文件的完整路径:

        for f in NETRC_FILES:
            try:
                loc = os.path.expanduser('~/{}'.format(f))

但是,这只是给出了我的主目录的路径,而 netrc 位于工作环境的 Lib 目录中。

显然,我在某处设置了错误的环境变量。有什么建议吗?

编辑问题:
根据 Steffen 的回应,netrc 似乎不是问题所在。 Marsiliou 关于直接包含证书文件路径的建议(即 resp = req.get("https://api.github.com" verify='/path/to/certfile')) 确实工作了......曾经......昨天。

我的代码现在看起来像这样:

import requests as req
from os import environ

cert_path = environ['CONDA_PREFIX'] + '\Lib\site-packages\certifi\cacert.pem'
print (cert_path)

resp = req.get("https://api.github.com", verify= cert_path)
print(resp.text)

cert_path 扩展为 C:\ProgramData\Anaconda3\Lib\site-packages\certifi\cacert.pem
这会导致相同的 SSLError。有什么建议(除了将verify 设置为False)?

PS - 并回答 Steffen 的其他问题 - 这是 Windows 10 上的 Anaconda3,Python 3.7.3。

【问题讨论】:

  • 我非常怀疑问题是从get_netrc_auth 内部触发的。问题是信任存储设置不正确,这意味着无法验证证书。不幸的是,您对您的系统一无所知(操作系统?,Anaconda3 的确切版本?),因此很难判断到底出了什么问题。
  • 谢谢,斯特凡。是的,你是对的;这个特殊的问题有点牵强附会。回答您的其他问题:Windows 10、Python 3.7.3。 Marsilinou 的回答确实解决了我的问题,但也提出了一个问题:既然certifirequests, 引用,而cacert.pemcertifi, 的一部分,为什么必须在函数调用中显式引用它?

标签: python ssl python-requests


【解决方案1】:

确保添加用户代理

import requests as req
# these import are for the verify false to avoid having a warning in the console
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning)
disable_warnings(InsecureRequestWarning)

Headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}
resp = req.get(url="https://api.github.com",headers=Headers, verify=False)
print(resp.text)

【讨论】:

  • 正确设置信任库后,代码无需任何特定用户代理即可完美运行。该代码抱怨证书验证失败。在发送 HTTP 请求之前,在 TLS 握手期间完成的证书验证因此在任何用户代理设置生效之前。
  • @SteffenUllrich 我知道这就是我添加验证错误的原因,但我遇到了类似的问题,用户代理是它的解决方案所以我说不要忘记添加它以防万一证书没有问题
【解决方案2】:

我想你的问题在这里得到了回答,你试过了吗? SSL HTTS requests.exceptions.SSLError: HTTPSConnectionPool(host='google.com', port=443)

【讨论】:

  • 谢谢!是的,这回答了它,有点。但是,由于 cacert.pem 包含在 certifi 包中(在 requests 包中引用),不应该自动拉入吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 2015-09-12
  • 2014-11-16
  • 1970-01-01
  • 2015-11-21
  • 2018-11-01
相关资源
最近更新 更多