使用 wincertstore 的 Python 请求

adi*_*i30 12 python ssl-certificate python-requests

我正在尝试通过请求包连接到我公司的内部网页,但由于 python 不使用 Windows 默认可信证书,因此连接被拒绝。我发现 wincertstore 可用于获取 Windows 默认证书。但我仍然不确定如何将它与我的请求一起使用。以下是我迄今为止尝试过的代码......

import requests, socket, atexit, ssl, wincertstore
from requests.auth import HTTPBasicAuth
certfile = wincertstore.CertFile()
certfile.addstore("CA")
certfile.addstore("ROOT")
atexit.register(certfile.close)
ssl_sock = ssl.wrap_socket(s,ca_certs=certfile.name, 
cert_reqs=ssl.CERT_REQUIRED)
requests.get(url)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误...... requests.exceptions.SSLError: HTTPSConnectionPool(host='myhost', port=443): Max retries exceeded with url: myurl (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

我可以在同一个网址上使用 wget 并下载内容。

wget --no check certificate --user=my username --password=my password URL

但我对下载内容不感兴趣,因为我只需要抓取网页内容的一小部分。

Python 版本 = 3.6.5

Wincertstore 链接 -链接

在此先感谢您的帮助..............

clf*_*ter 19

我有一个类似的问题并使用 python-certifi-win32 包修复它:

pip install python-certifi-win32
Run Code Online (Sandbox Code Playgroud)

现在你可以使用:

requests.get(url, verify=True)
Run Code Online (Sandbox Code Playgroud)

并且使用 Windows 证书存储检查证书。

编辑:这仅适用于证书安装在 Windows 证书存储区...

  • 或使用 anaconda 节省恩典 `conda install -c conda-forge python-certifi-win32` (3认同)
  • 不幸的是,“python-certifi-win32”似乎[不再维护](/sf/answers/5085357231/)。`pip-system-certs`(由同一作者)对我来说非常适合作为直接替代品。 (3认同)

aba*_*ert 8

这一切都在文档的SSL 证书验证部分进行了解释requests

默认情况下,requests使用certifiif 存在的证书,回退到任何urllib3认为是您的操作系统证书存储的地方,它本身回落到 Python 认为的任何东西(尽管在旧版本中通常没有)。

您的公司显然有一个私有的,甚至可能是自签名的证书,它不会在certifi. 它可能在 Windows 证书存储中——在这种情况下urllib3应该自动选择它——但我怀疑它不是。也许证书直接安装到您的 IT 部门强制您使用的某些自定义浏览器设置中,而不是安装到操作系统商店中。或者它根本没有安装。(您没有提到能够在浏览器中访问此站点而不会看到坏锁图标……)

您正在传递--no check certificate(或者,更有可能是--no-check-certificate?)到wget,因此您只是没有验证 SSL。如果你想在 中做同样的事情requests,那就是:

requests.get(url, verify=False)
Run Code Online (Sandbox Code Playgroud)

如果您非常确定您确实安装了证书,即使wget找不到它……好吧,您的代码将不会像编写的那样工作。这是可行的:

  • 忽略证书并仅禁用验证,如上所示。
  • 找出相关证书的实际安装位​​置以及如何加载它,并且:
    • verify在每次requests调用时将其作为参数传递。
    • 将它静态地设置在某个地方并将其传递到环境变量中。
    • 将其安装到您的默认证书存储中,以便一切自动运行。
    • 编写一个HTTPAdapter将其安装到您的requests会话中。

首先,您的代码只是试图以与 Python 已经完全相同的方式获取默认证书。该wincertstore模块只是 Python 3.4+ 内置功能的反向移植。

其次,您的代码所做的就是获取证书,使用它来创建 SSL 套接字,忽略该套接字,并告诉requests它做正常的事情。那不会有任何帮助。如果您想将证书传递给requests,您可以这样做:

requests.get(url, verify='/path/to/cert')
Run Code Online (Sandbox Code Playgroud)

... 或者把它放在环境变量中 REQUESTS_CA_BUNDLE

……或者执行HTTPAdapter我在聊天中向您展示的代码(并且您在某个未指定的地方发现了一个旧的、无法工作的版本)。HTTPAdapter如果您真的想这样做,请参阅文档。

  • “requests”文档的链接现在悬空。也许 https://requests.readthedocs.io/en/master/user/advanced/#ssl-cert-verification 将是一个合适的替代品,但它没有任何关于“urllib3”和 wotnot 的令人印象深刻的细节。 (2认同)