禁用Python请求导入模块的SSL验证

Mos*_*she 4 python ssl python-requests

我正在运行一个Python脚本,该脚本使用该requests包来发出Web请求.但是,Web请求通过具有自签名证书的代理进行.因此,请求引发以下异常:

requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)

我知道通过传递可以在我自己的代码中禁用SSL验证verify=False,例如:requests.get("https://www.google.com", verify=False).我也知道如果我有证书包,我可以设置REQUESTS_CA_BUNDLECURL_CA_BUNDLE环境变量指向那些文件.但是,我没有可用的证书包.

如何在不编辑代码的情况下禁用外部模块的SSL验证?

Mos*_*she 18

注意:此解决方案是一个完整的黑客.

简答:将CURL_CA_BUNDLE环境变量设置为空字符串.

之前:

$ python
import requests
requests.get('http://www.google.com')
<Response [200]>

requests.get('https://www.google.com')
...
File "/usr/local/lib/python2.7/site-packages/requests-2.17.3-py2.7.egg/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)
Run Code Online (Sandbox Code Playgroud)

后:

$ CURL_CA_BUNDLE="" python
import requests
requests.get('http://www.google.com')
<Response [200]>

requests.get('https://www.google.com')
/usr/local/lib/python2.7/site-packages/urllib3-1.21.1-py2.7.egg/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)
<Response [200]>
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

该解决方案的工作因为Python requests覆盖缺省值verify从环境变量CURL_CA_BUNDLEREQUESTS_CA_BUNDLE,可以看出这里:

if verify is True or verify is None:
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
    os.environ.get('CURL_CA_BUNDLE'))
Run Code Online (Sandbox Code Playgroud)

环境变量用于指定证书文件或CA_BUNDLE的路径并将其复制到其中verify.但是,通过设置CURL_CA_BUNDLE为空字符串,空字符串将被复制到verifyPython中,而空字符串的计算结果为False.

请注意,此hack仅适用于CURL_CA_BUNDLE环境变量 - 它不适用于REQUESTS_CA_BUNDLE.这是因为verify 使用以下语句设置:

verify = (os.environ.get('REQUESTS_CA_BUNDLE') or os.environ.get('CURL_CA_BUNDLE'))

它只适用于CURL_CA_BUNDLE因为'' or None不一样None or '',如下所示:

print repr(None or "")
# Prints: ''
print repr("" or None )
# Prints: None
Run Code Online (Sandbox Code Playgroud)

  • 我已经在 Unix 上成功使用了这种技术,但无法让它在 Windows 上工作 (4认同)
  • 这不再适用于请求 2.28.0 或更高版本,因为它被认为是一个错误,请参阅 https://github.com/psf/requests/issues/6071... (4认同)
  • 这在简单性和黑客性方面是令人惊奇的:) 确认这可以按照 macOS 10.14 上使用 Python 3.7/3.8 的描述进行工作。 (3认同)
  • @David:这就是变量在 Bash 和类似 shell 中的工作方式。如果您只是执行 `CURL_CA_BUNDLE=""`,则只会在该特定 shell 的上下文中或同一行后面的命令中设置变量。如果您使用 `export CURL_CA_BUNDLE=""`,那么它也将适用于从该 shell 启动的任何新进程,例如 Python(但仍然不是完全独立的进程中的进程)。 (2认同)