禁用 Python 请求对导入的模块进行 SSL 验证 [英] Disable Python requests SSL validation for an imported module

查看:22
本文介绍了禁用 Python 请求对导入的模块进行 SSL 验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm running a Python script that uses the requests package for making web requests. However, the web requests go through a proxy with a self-signed cert. As such, requests raise the following Exception:

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

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

I know that SSL validation can be disabled in my own code by passing verify=False, e.g.: requests.get("https://www.google.com", verify=False). I also know that if I had the certificate bundle, I could set the REQUESTS_CA_BUNDLE or CURL_CA_BUNDLE environment variables to point to those files. However, I do not have the certificate bundle available.

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

How can I disable SSL validation for external modules without editing their code?

推荐答案

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

Note: This solution is a complete hack.

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

Short answer: Set the CURL_CA_BUNDLE environment variable to an empty string.

之前:

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

工作原理

此解决方案有效,因为 Python requests 覆盖了环境变量 CURL_CA_BUNDLEREQUESTS_CA_BUNDLEverify 的默认值,如此处所示:

This solution works because Python requests overwrites the default value for verify from the environment variables CURL_CA_BUNDLE and REQUESTS_CA_BUNDLE, as can be seen here:

if verify is True or verify is None:
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
    os.environ.get('CURL_CA_BUNDLE'))

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

The environment variables are meant to specify the path to the certificate file or CA_BUNDLE and are copied into verify. However, by setting CURL_CA_BUNDLE to an empty string, the empty string is copied into verify and in Python, an empty string evaluates to False.

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

Note that this hack only works with the CURL_CA_BUNDLE environment variable - it does not work with the REQUESTS_CA_BUNDLE. This is because verify is set with the following statement:

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

它只适用于 CURL_CA_BUNDLE 因为 '' or NoneNone or '' 不同,如下所示:

It only works with CURL_CA_BUNDLE because '' or None is not the same as None or '', as can be seen below:

print repr(None or "")
# Prints: ''
print repr("" or None )
# Prints: None

这篇关于禁用 Python 请求对导入的模块进行 SSL 验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆