如何禁用请求中的主机名检查python
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22758031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to disable hostname checking in requests python
提问by user3480498
I'm using Requests to connect to a RESTful API. The server I would like to reach use ssl with self-singed certificate.
我正在使用请求连接到 RESTful API。我想访问的服务器使用带有自签名证书的 ssl。
cafile = "gateway.pem"
r = requests.get(request, auth=('admin', 'password'), verify=cafile)
the problem is I'm getting SSLError of hostname mismatch. there should be a way to disable the hostname checking without disabling certificate validation, as in many java implementations, but I can't find how to do it with requests in python.
问题是我收到主机名不匹配的 SSLError。应该有一种方法可以在不禁用证书验证的情况下禁用主机名检查,就像在许多 Java 实现中一样,但是我在 python 中找不到如何处理请求的方法。
stacktrace:
堆栈跟踪:
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
r = requests.get(request, auth=("admin", "password"), verify='gateway.pem')
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\api.py", line 55, in get
return request('get', url, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\sessions.py", line 357, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\sessions.py", line 460, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\adapters.py", line 358, in send
raise SSLError(e)
SSLError: hostname '10.76.92.70' doesn't match u'lital.com'
How can this be done?
如何才能做到这一点?
回答by m.wasowski
http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification
http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification
verify
keyword is a flag, not for providing certfile. You provided there non-empy string, which resolves to True
in boolean context.
verify
关键字是一个标志,不用于提供证书文件。您在那里提供了非空字符串,它True
在布尔上下文中解析为。
Use cert=
keyword to provide path to certificate files, or disable verification with verify=False
.
使用cert=
关键字提供证书文件的路径,或使用verify=False
.
EDIT: although documentation says you can actually pass CA path to verify=
, but there are no examples. It would be helpful to see whole traceback you are receiving.
编辑:虽然文档说您实际上可以将 CA 路径传递给verify=
,但没有示例。查看您收到的整个追溯会很有帮助。
回答by t-8ch
Requests doesn't allow this directly, however you can provide a custom transport adapter which uses the features of the underlying urllib3
. The usage of transport adapters is covered in the requests documentation.
Requests 不允许直接这样做,但是您可以提供一个自定义传输适配器,它使用底层urllib3
. 请求文档中介绍了传输适配器的使用。
This code is not tested, but should work.
此代码未经测试,但应该可以工作。
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
# Never check any hostnames
class HostNameIgnoringAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
assert_hostname=False)
# Check a custom hostname
class CustomHostNameCheckingAdapter(HTTPAdapter):
def cert_verify(self, conn, url, verify, cert):
# implement me
host = custom_function_mapping_url_to_hostname(url)
conn.assert_hostname = host
return super(CustomHostNameCheckingAdapter,
self).cert_verify(conn, url, verify, cert)
In detail the assert_hostname
param works as follows:
If None
use the hostname from the URL, if False
suppress hostname checking, if a custom string validate against this string.
assert_hostname
参数的详细工作如下:如果None
使用来自 URL 的主机名,如果False
禁止主机名检查,如果自定义字符串针对此字符串进行验证。
回答by Alecz
Did you look into the SSLContext.check_hostname
parameter?
You should be able to set it to False, and it should not check the hostname:
你看SSLContext.check_hostname
参数了吗?您应该能够将其设置为 False,并且不应检查主机名:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
The only limitation is that this only works in Python 3.4 and later.
唯一的限制是这只适用于 Python 3.4 及更高版本。
Reference: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.check_hostname
参考:https: //docs.python.org/3/library/ssl.html#ssl.SSLContext.check_hostname
回答by user3644848
If this is only for testing only then just add an entry in /etc/hosts to your local system (assuming you have access).
如果这仅用于测试,那么只需将 /etc/hosts 中的条目添加到本地系统(假设您有权访问)。
回答by lane
I'm a little late to the party but requests_toolbelt
looks like it might help if you install version 0.7.0 or newer (my ubuntu 16.04 only has 0.6.0): https://toolbelt.readthedocs.io/en/latest/adapters.html#hostheaderssladapter
我参加聚会有点晚了,但requests_toolbelt
如果您安装 0.7.0 或更高版本(我的 ubuntu 16.04 只有 0.6.0),看起来可能会有所帮助:https: //toolbelt.readthedocs.io/en/latest/adapters .html#hostheaderssladapter
From the link:
从链接:
Example usage:
>>> s.mount('https://', HostHeaderSSLAdapter())
>>> s.get("https://93.184.216.34", headers={"Host": "example.org"})
回答by mojoken
It looks like this feature has been added to the latest version of requests. I've verified and it's working for me - just pass verify=False on the request - as shown in the example in the documentation:
看起来此功能已添加到最新版本的请求中。我已经验证并且它对我有用 - 只需在请求中传递 verify=False - 如文档中的示例所示:
requests.get('https://api.github.com', verify=False)