【问题标题】:python requests ssl handshake failurepython请求ssl握手失败
【发布时间】:2015-07-27 09:24:43
【问题描述】:

每次我尝试做的时候:

requests.get('https://url') 

我收到了这条消息:

import requests
>>> requests.get('https://reviews.gethuman.com/companies') 
Traceback (most recent call last): 
   File "<stdin>", line 1, in <module> 
   File "/usr/lib/python2.7/dist-packages/requests/api.py", line 55, in get 
    return request('get', url, **kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request 
    return session.request(method=method, url=url, **kwargs)    
   File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 455, in request 
    resp = self.send(prep, **send_kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 558, in send 
    r = adapter.send(request, **kwargs) 
   File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 385, in send 
    raise SSLError(e) requests.exceptions.SSLError: [Errno 1]
_ssl.c:510: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

我什么都试过了:

  • 更新我的请求
  • 更新我的 ssl

但没有任何变化。

我使用的是 Python 2.7.6,无法更改。

【问题讨论】:

  • 看起来你必须在呼叫请求时强制使用 sslv3。请参阅stackoverflow.com/questions/22857889/… 了解更多详情。
  • 您尝试的每个 https url 是否都有问题,或者特别是其中一个?我试过requests.get('https://reviews.gethuman.com/companies')没有问题
  • 这是您使用的实际网址吗?
  • 是的,这是实际的 url,没什么特别的。我在每个 https 中都遇到了问题,我试图让它看起来更新我的 ubuntu 可以解决问题,但我还不知道为什么

标签: python python-requests


【解决方案1】:
import requests

#Add support for all cipher suites
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS='ALL'
#Exclude use of pyopenssl (pyopenssl module may need to be installed first $pip install pyopenssl)
requests.packages.urllib3.contrib.pyopenssl.extract_from_urllib3()

【讨论】:

  • 当人们想要快速和临时解决这类问题时,这是一个被低估的答案。
【解决方案2】:

我使用的是python 2.7.6 无法更改。

那么对不起。您尝试访问的服务器需要(SNI) Server Name Indication,如果客户端未使用此 SNI 扩展,则会导致握手失败。仅在 python 2.7.9 中添加了对 SNI 的支持,所以看起来您不走运。

【讨论】:

  • 没有dv,但是通过安装请求的[security]扩展,这不是可能的吗,因此您仍然可以在2.7.6中支持SNI?
  • @jonnybazookatone:可能是,但它没有真正记录在案,也许它还有一些意想不到的副作用(同样,缺少详细的文档)。
  • 是的。关于不支持的请求的文档存在冲突:docs.python-requests.org/en/master/community/faq for python2.6 和 python2.7.0-2.7.8urllib3.readthedocs.io/en/latest/security.html 很好。然而,这个关于请求的 PR 似乎表明 SNI 很好:github.com/kennethreitz/requests/pull/1347
  • 事实上,点击请求文档上的 SO 问题会指向包含 2.6-3 的 SNI 的请求 PR。我认为可以肯定地说它有效。
  • @jonnybazookatone:是的,它可能会起作用,但是由于实现不再基于 ssl.py,而是基于 pyOpenSSL,因此可能会出现意想不到的行为差异。
【解决方案3】:

在 OSX 上,使用 python 2.7.10 / requests 2.9.1 我只需要安装requests使用它的安全设置:

pip install requests[security]

这将安装pyOpenSSLndg-httpsclientpyasn1https://github.com/kennethreitz/requests/blob/master/setup.py#L70

【讨论】:

  • 使用其安全设置安装requests 似乎也可以在 Windows 上运行,谢谢!
  • 我必须先升级 pip 才能执行此操作,但它在 OS X 10.5 上运行。
  • 这为我解决了 Python 3.5.3 的问题,并在 Debian 9.2 (stretch) 上请求了 2.18.4。感谢您的提示!
  • 在特定站点对我不起作用:python 成功安装 asn1crypto-0.24.0 cffi-1.11.5 cryptography-2.3.1 enum34-1.1.6 ipaddress-1.0.22 pyOpenSSL-18.0 .0 pycparser-2.19 Python 2.7.15(默认,2018 年 6 月 17 日,12:46:58)[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
【解决方案4】:

我最终解决了这个问题,我将我的 ubuntu 从 14.04 更新到 14.10,问题就解决了

但是在旧版本的 ubuntu 和 python 中,我安装了这些库,它似乎解决了我所有的问题

sudo apt-get install python-dev libssl-dev libffi-dev
sudo pip2.7 install -U pyopenssl==0.13.1 pyasn1 ndg-httpsclient

如果你没有安装 pip2.7,你可以使用 pip 代替

【讨论】:

  • 太棒了!解决了我的 httpie 问题(使用 pip 而不是 pip2.7)
  • 也为我工作。
  • 我收到“无法获取索引基础 URL pypi.python.org/simple”。可以请教吗?
【解决方案5】:

运行 python 2.7.13。我在这里尝试了推荐的解决方案,最终安装了以下内容:

  • pip install requests[security](已安装 asn1crypto-0.24.0 cffi-1.11.5 cryptography-2.4.2 idna-2.7 ipaddress-1.0.22 ndg-httpsclient-0.5.1 pyOpenSSL-18.0.0 pyasn1-0.4.4 pycparser-2.19)

没有帮助,然后尝试了

  • pip install -U requests(已安装 certifi-2018.10.15 chardet-3.0.4 requests-2.20.1 urllib3-1.24.1)

没有帮助。终于试过了

  • pip install -U httplib2 (httplib2-0.12.0)

解决了这个问题。以前我在运行 httplib2==0.9.2

【讨论】:

    【解决方案6】:

    在尝试了上述所有解决方案并陷入困境之后,最终破解此案的只是尝试从 urllib3 包中导入 pyopenssl,如下所示:

    from urllib3.contrib import pyopenssl

    这导致我出错(缺少cryptography 包)

    【讨论】:

    • 只需安装cryptography 包即可解决问题,但我只能通过尝试pyopenssl 导入才能看到问题所在
    • 将'from urllib3.contrib import pyopenssl'添加到源代码,然后我尝试调试代码,然后我收到错误“ImportError: No module named ndg.httpsclient.ssl_peer_verification”,然后我安装了 ndg.httpsclient使用 'sudo pip install pyasn1 ndg-httpsclient' ,这解决了我的问题
    【解决方案7】:

    如果您无法将 Python 版本升级到 2.7.9,则将您的请求包降级到 2.5.3。这对我有用。

    sudo pip install requests==2.5.3
    

    编辑

    您还可以安装带有安全扩展的请求

    pip install requests[security]
    

    【讨论】:

    • 不幸的是,降级请求是唯一对我有用的解决方案。 requests==2.11.1 是我没有收到此错误的最后一个版本。 2.12开始抛出错误。
    • 这似乎也对我有用。我在 linux mint Rebecca 上使用 python 2.7.6
    【解决方案8】:

    在使用过时的 HTTPS 连接到旧网站时,我不断收到此错误消息。

    最后,我必须使用适配器手动设置协议和密码才能使请求正常工作。

    什么对我有用 -

    1. 去一个像这样的诊断站点https://www.ssllabs.com/ssltest/analyze.html
    2. 找出网站使用的协议(TLS1.0、TLS1.2、SSL3.0(仅限?)...)
    3. 找出使用了哪些过时的密码套件
    4. 从 3) 将密码名称转换为列表中的 openssl 名称,如 https://www.openssl.org/docs/man1.1.0/apps/ciphers.htmlhttp://testssl.sh/openssl-rfc.mapping.html 以在代码中使用

    然后在请求中使用您在上面研究过的内容创建一个适配器

    import requests, ssl
    from requests.adapters import HTTPAdapter
    from requests.packages.urllib3.poolmanager import PoolManager
    from requests.packages.urllib3.util import ssl_
    
    class OldInsecureWebsiteAdapter(HTTPAdapter):
        def __init__(self, **kwargs):
            super(OldInsecureWebsiteAdapter, self).__init__(**kwargs)
        def init_poolmanager(self, *pool_args, **pool_kwargs):
            """
            my website uses TLS1.0 ONLY (from step 2) 
            and several obsolete ciphers (from step 3/4 I only picked one)
            """
            context = ssl_.create_urllib3_context(ssl.PROTOCOL_TLSv1, ciphers="DES-CBC3-SHA")
    
            """
            website does not support anything else so exclude all other protocols
            """
            context.options |= ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_3 | ssl.OP_NO_TLSv1_2 
            context.options |= ssl.OP_NO_SSLv3 | ssl.OP_NO_SSLv2
    
            self.poolmanager = PoolManager(*pool_args,
                                       ssl_context=context,
                                       **pool_kwargs)
    

    现在我将适配器安装到请求对象

        url = "https://yourwebsite.gov.whocares"
        session = requests.session()
        session.mount(url, OldInsecureWebsiteAdapter())
        result = session.get(url) 
        #no more ssl3 handshake error...
    

    【讨论】:

      【解决方案9】:

      您只需要升级您的请求。

      pip 安装请求 --upgrade

      你仍然可以使用 python 2.7。

      【讨论】:

        猜你喜欢
        • 2018-07-28
        • 2015-05-19
        • 2012-10-11
        • 2015-03-16
        • 2021-12-28
        • 2018-10-17
        • 2016-04-29
        • 2014-03-05
        相关资源
        最近更新 更多