Python 使用带有 TLS 的请求不提供 SNI 支持

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18578439/
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 11:08:22  来源:igfitidea点击:

using requests with TLS doesn't give SNI support

pythonsslssl-certificatepython-requestssni

提问by Massagran

I'm using requests to communicate with a django app but

我正在使用请求与 django 应用程序进行通信,但是

When I try

当我尝试

requests.get('https://mysite.com', verify=True)

I get the error:

我收到错误:

hostname 'mysite.com' doesn't match either of '*.myhost.com', 'myhost.com'

主机名“mysite.com”与“*.myhost.com”、“myhost.com”中的任何一个都不匹配

However, when I look at the browser, or http://www.digicert.com/help/the certificate looks fine and dandy.

但是,当我查看浏览器或http://www.digicert.com/help/ 时,证书看起来不错。

My host suggested it was the lack of SNI support from requests (and Github seems to confirm that https://github.com/kennethreitz/requests/issues/749). Has anyone found a work-around using requests?

我的主持人建议这是请求缺乏 SNI 支持(并且 Github 似乎确认https://github.com/kennethreitz/requests/issues/749)。有没有人找到使用请求的解决方法?

采纳答案by Lukasa

The current version of Requests should be just fine with SNI. Further down the GitHub issueyou can see the requirements:

当前版本的 Requests 应该可以与 SNI 配合使用。在 GitHub 问题的进一步下方,您可以看到要求:

Try installing those packages and then give it another shot.

尝试安装这些软件包,然后再试一次。

EDIT: As of Requests v2.12.1, ndg-httpsclient and pyasn1 are no longer required. The full list of required packages is now:

编辑:从请求 v2.12.1 开始,不再需要 ndg-httpsclient 和 pyasn1。所需软件包的完整列表现在是:

  • pyOpenSSL
  • idna
  • 开放式SSL
  • 伊德娜

回答by AntonioMO

@Lukasa answer is correct with the present (from github) requests. Remember to add OpenSSL in your system too apart from the pip dependencies he mentions.

@Lukasa 的回答对当前(来自 github)的请求是正确的。除了他提到的 pip 依赖项之外,请记住在您的系统中添加 OpenSSL。

If for deployment reasons you prefer a stable requests version like the 1.2.3 in pip, you can monkey patch that one to work with SNI like this:

如果出于部署原因,您更喜欢像 pip 中的 1.2.3 这样的稳定​​请求版本,则可以像这样修补该版本以与 SNI 一起使用:

import requests


def fileno(self):
    return self.socket.fileno()


def close(self):
    return self.connection.shutdown()


requests.pyopenssl.WrappedSocket.close = close
requests.pyopenssl.WrappedSocket.fileno = fileno

回答by Shane N

In order for me to get the accepted answer to work, I had to install a bunch of other packages, in this order:

为了让我得到可接受的工作答案,我必须按以下顺序安装一堆其他软件包:

  • yum install libffi-devel
  • yum install gcc
  • yum install openssl-devel
  • pip install urllib3
  • pip install pyopenssl
  • pip install ndg-httpsclient
  • pip install pyasn1
  • yum 安装 libffi-devel
  • yum 安装 gcc
  • yum 安装 openssl-devel
  • pip 安装 urllib3
  • pip 安装 pyopenssl
  • pip 安装 ndg-httpsclient
  • pip安装pyasn1

回答by stantonk

Or you can just use Python 2.7.9 and up:

或者你可以只使用 Python 2.7.9 及更高版本:

"The entirety of Python 3.4's ssl module has been backported for Python 2.7.9. See PEP 466 for justification."

“Python 2.7.9 的整个 Python 3.4 的 ssl 模块都已向后移植。有关理由,请参阅 PEP 466。”

https://www.python.org/downloads/release/python-279/

https://www.python.org/downloads/release/python-279/

回答by Nandeesh

Install requests module like this. This will install the security package extras.

像这样安装请求模块。这将安装额外的安全包。

pip install requests[security]

pip install requests[security]

回答by Xb74Dkjb

Copy my answer from Accessing https sites with IP address

使用 IP 地址访问 https 站点复制我的答案

On MAC High Sierra and Python 3.6.4, I tried the solution: requests toolbelt:HostHeaderSSLAdapter1st, unfortunately, it doesn't work for me, then I tried forcediphttpsadapter, got it works finally.

在 MAC High Sierra 和 Python 3.6.4 上,我尝试了解决方案:requests toolbelt:HostHeaderSSLAdapter1st,不幸的是,它对我不起作用,然后我尝试了 forceiphttpsadapter,最终使它起作用。

The author explains everything in the readme part and has provided a sample script and it can be followed easily.

作者在自述部分解释了所有内容,并提供了一个示例脚本,可以轻松遵循。

1.Install the library by pip install requests[security] forcediphttpsadapter

1.安装库 pip install requests[security] forcediphttpsadapter

2.run the sample script:

2.运行示例脚本:

import requests
from forcediphttpsadapter.adapters import ForcedIPHTTPSAdapter
session = requests.Session()
session.mount("https://example.com", ForcedIPHTTPSAdapter(dest_ip='1.2.3.4'))
response = session.get(
    '/some/path', headers={'Host': 'example.com'}, verify=False)

Note: For some cases, you may need to remove the prefix: 'www' from the url.

注意:在某些情况下,您可能需要从 url 中删除前缀:“www”。