为什么 Python 请求会忽略 verify 参数?
Why does Python requests ignore the verify parameter?
问题
我一直在尝试使用Python的请求包下载以下URL:
在 Chrome 中,证书似乎有效:
然而,在 Python 中,请求失败 SSLV3_ALERT_HANDSHAKE_FAILURE
,即使 using the verify
flag 忽略了错误的证书:
Requests can also ignore verifying the SSL certificate if you set verify to False
堆栈跟踪
>>> 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)
环境
OS 和包
我在 OSX 上的虚拟环境中使用请求 2.7.0 和 Python 2.7.10。
cURL
cURL 在同一台机器上调用相同的 URL 工作正常:
$ 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=/
证书验证没有失败,所以verify
参数在这里不适用。失败的是密码协商; none requests
愿意使用的密码匹配服务器愿意使用的密码。
如果您 运行 使用 -v
开关的 curl
命令,您将看到 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 and should not really be used; it offers no forward secrecy。默认情况下,urllib3
包(与 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
受保护的部分。
我 运行 在 macOS Sierra Python 2.7.9 上也加入了这个,它被修复了:
sudo pip install --ignore-installed pyOpenSSL --upgrade
可能是因为pyOpenSSL太旧了。
结合 OpenSSL 升级和安装 ndg-httpsclient
为我解决了这个问题
sudo pip install ndg-httpsclient
和
sudo pip install --ignore-installed pyOpenSSL --upgrade
问题
我一直在尝试使用Python的请求包下载以下URL:
在 Chrome 中,证书似乎有效:
然而,在 Python 中,请求失败 SSLV3_ALERT_HANDSHAKE_FAILURE
,即使 using the verify
flag 忽略了错误的证书:
Requests can also ignore verifying the SSL certificate if you set verify to False
堆栈跟踪
>>> 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)
环境
OS 和包
我在 OSX 上的虚拟环境中使用请求 2.7.0 和 Python 2.7.10。
cURL
cURL 在同一台机器上调用相同的 URL 工作正常:
$ 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=/
证书验证没有失败,所以verify
参数在这里不适用。失败的是密码协商; none requests
愿意使用的密码匹配服务器愿意使用的密码。
如果您 运行 使用 -v
开关的 curl
命令,您将看到 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 and should not really be used; it offers no forward secrecy。默认情况下,urllib3
包(与 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
受保护的部分。
我 运行 在 macOS Sierra Python 2.7.9 上也加入了这个,它被修复了:
sudo pip install --ignore-installed pyOpenSSL --upgrade
可能是因为pyOpenSSL太旧了。
结合 OpenSSL 升级和安装 ndg-httpsclient
为我解决了这个问题
sudo pip install ndg-httpsclient
和
sudo pip install --ignore-installed pyOpenSSL --upgrade