J'ai essayé d'utiliser le paquet de requêtes de Python pour télécharger l'URL suivante:
Dans Chrome, le certificat semble valide:
Cependant, en Python, la requête échoue avec SSLV3_ALERT_HANDSHAKE_FAILURE
, même si en utilisant l'indicateur verify
qui ignore les certificats erronés:
Les demandes peuvent également ignorer la vérification du certificat SSL si vous définissez vérifier à 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)
J'utilise les demandes 2.7.0 et Python 2.7.10 dans un environnement virtuel sous OSX.
l'appel de cURL à la même URL sur la même machine fonctionne bien:
$ 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=/
La validation du certificat n'a pas échoué, l'argument verify
ne s'applique donc pas ici. Ce qui a échoué est la négociation de chiffrement; aucun des chiffrements requests
ne veut utiliser une correspondance avec ceux que le serveur est prêt à utiliser.
Si vous exécutez votre commande curl
avec le commutateur -v
, vous verrez quelle suite de chiffrement a été négociée par curl
pour la connexion établie:
$ 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
[ .... ]
C'est le chiffre RC4-SHA, qui a quelques problèmes de sécurité plutôt gênants et qui ne devrait pas vraiment être utilisé; il n'offre aucun secret de transfert par exemple. Le package urllib3
(fourni avec requests
) par défaut exclut ce chiffrement des chiffrements par défaut. Vous pouvez le rajouter avec:
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
et votre demande fonctionne:
>>> import requests
>>> requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'
>>> requests.get('https://service.isracard.co.il/I_logon.jsp')
<Response [200]>
Je n’ai pas installé le paquet pyOpenSSL, je ne me suis donc pas soucié de la partie gardée par try..except
.
Je rencontre également ce problème sur macOS Sierra, Python 2.7.9 et il est corrigé par:
Installation de pipettes Sudo - pyOpenSSL - amélioré par la version installée
C'est probablement dû au fait que le pyOpenSSL est trop vieux.
La combinaison de la mise à niveau et de l'installation d'OpenSSL ndg-httpsclient
l'a résolue pour moi
Sudo pip install ndg-httpsclient
et
Sudo pip install --ignore-installed pyOpenSSL --upgrade