为什么Python请求会忽略验证参数?

时间:2015-09-18 11:31:46

标签: ssl ssl-certificate python-requests

问题

我一直在尝试使用Python的请求包下载以下网址:

  

https://service.isracard.co.il/I_logon.jsp

在Chrome中,证书似乎有效:

enter image description here

但是,在Python中,请求失败了SSLV3_ALERT_HANDSHAKE_FAILURE,即使using the verify flag忽略了错误的证书:

  

如果将verify设置为False

,请求也可以忽略验证SSL证书

堆栈跟踪

>>> requests.__version__
'2.7.0'
>>> LOGIN_URL = 'https://service.isracard.co.il/I_logon.jsp'
>>> requests.get(LOGIN_URL, verify=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/private/tmp/sslenv/lib/python2.7/site-packages/requests/adapters.py", line 431, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590)

环境

操作系统和软件包

我在OSX上的虚拟环境中使用请求2.7.0和Python 2.7.10。

卷曲

在同一台机器上调用同一个URL的cURL工作正常:

 $ curl -I https://service.isracard.co.il/I_logon.jsp
HTTP/1.1 200 OK
Date: Fri, 18 Sep 2015 11:37:27 GMT
Server: IBM_HTTP_Server
X-Powered-By: Servlet/3.0
Set-Cookie: JSESSIONID=0000R90MxFKBVxBMV665syGfjnh:-1; Path=/; HttpOnly
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: no-cache="set-cookie, set-cookie2"
Set-Cookie: Alt50_ZLinuxPrd=94742720.30755.0000; expires=Fri, 18-Sep-2015 12:07:19 GMT; path=/
Content-Type: text/html; charset=ISO-8859-8
Content-Language: iw-IL
Set-Cookie: ServiceP=53323968.20480.0000; path=/

3 个答案:

答案 0 :(得分:18)

证书验证没有失败,因此verify参数不适用于此处。失败的是密码协商;没有一个密码requests愿意使用服务器愿意使用的匹配。

如果您使用curl开关运行-v命令,您将看到curl为成功连接协商了哪些密码套件:

$ curl -v -I https://service.isracard.co.il/I_logon.jsp
* Hostname was NOT found in DNS cache
*   Trying 192.118.12.8...
* Connected to service.isracard.co.il (192.118.12.8) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_SHA
[ .... ]

这是RC4-SHA密码,它有some rather troublesome securty issues并且不应该被使用;例如,它不提供forward secrecyurllib3软件包(与requests捆绑在一起)默认情况下从默认密码中排除该密码。您可以将其添加回:

import requests

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
try:
    requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += ':RC4-SHA'
except AttributeError:
    # no pyopenssl support used / needed / available
    pass

并且您的请求有效:

>>> import requests
>>> requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
>>> requests.get('https://service.isracard.co.il/I_logon.jsp')
<Response [200]>

我没有安装pyOpenSSL包,所以我没有打扰try..except防护部分。

答案 1 :(得分:6)

我在macOS Sierra,Python 2.7.9上遇到了这个问题,它由以下版本修复:

  

sudo pip install --ignore-installed pyOpenSSL --upgrade

这可能是由于pyOpenSSL太旧了。

答案 2 :(得分:0)

OpenSSL升级和安装ndg-httpsclient的组合为我解决了

sudo pip install ndg-httpsclient

sudo pip install --ignore-installed pyOpenSSL --upgrade