如何禁用请求中的主机名检查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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:36:41  来源:igfitidea点击:

How to disable hostname checking in requests python

pythonsslpython-requests

提问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

verifykeyword is a flag, not for providing certfile. You provided there non-empy string, which resolves to Truein 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_hostnameparam works as follows: If Noneuse the hostname from the URL, if Falsesuppress hostname checking, if a custom string validate against this string.

assert_hostname参数的详细工作如下:如果None使用来自 URL 的主机名,如果False禁止主机名检查,如果自定义字符串针对此字符串进行验证。

回答by Alecz

Did you look into the SSLContext.check_hostnameparameter? 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_toolbeltlooks 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)