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
using requests with TLS doesn't give SNI support
提问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。”
回答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”。