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

时间:2018-01-22 23:14:16

标签: python ssl python-requests

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

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

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

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

1 个答案:

答案 0 :(得分:12)

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

简短回答:将$ 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')],)",) 环境变量设置为空字符串。

在:

$ 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]>

后:

requests

工作原理

此解决方案有效,因为Python verify会覆盖环境变量CURL_CA_BUNDLEREQUESTS_CA_BUNDLEif verify is True or verify is None: verify = (os.environ.get('REQUESTS_CA_BUNDLE') or os.environ.get('CURL_CA_BUNDLE')) 的默认值,如here所示:< / p>

verify

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

请注意,此hack仅适用于REQUESTS_CA_BUNDLE环境变量 - 它不适用于verify。这是因为verify = (os.environ.get('REQUESTS_CA_BUNDLE') or os.environ.get('CURL_CA_BUNDLE')) is set with the following statement

CURL_CA_BUNDLE

它仅适用于'' or None,因为None or ''print repr(None or "") # Prints: '' print repr("" or None ) # Prints: None 不同,如下所示:

<form>
<input type="text">
<input type="submit">
</form>