web-dev-qa-db-fra.com

python ignore la validation du certificat urllib2

Je veux ignorer le certification validation lors de ma demande au serveur avec un lien d'entreprise interne.

Avec la bibliothèque python requests, je ferais ceci:

r = requests.get(link, allow_redirects=False,verify=False)

Comment faire la même chose avec la bibliothèque urllib2?

46
Sangamesh Hs

urllib2 ne vérifie pas le certificat de serveur par défaut. Vérifiez ceci documentation.

Edit: Comme indiqué dans le commentaire ci-dessous, ceci n’est plus vrai pour les versions plus récentes (> = 2.7.9) de Python. Voir ci-dessous RÉPONSE

4
thavan

En attendant, urllib2 semble vérifier les certificats de serveur par défaut. Le avertissement, qui a été montré dans le passédispar pour 2.7.9 et je rencontre actuellement ce problème dans un environnement de test avec un certificat auto-signé (et Python 2.7.9).

Mon mal solution de contournement (ne le faites pas en production!):

import urllib2
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

urllib2.urlopen("https://your-test-server.local", context=ctx)

Selon docs appeler le constructeur SSLContext directement devrait également fonctionner. Je n'ai pas essayé ça.

125
Enno Gröper

Le moyen le plus simple:

python 2

import urllib2, ssl

request = urllib2.Request('https://somedomain.co/')
response = urllib2.urlopen(request, context=ssl._create_unverified_context())

python

from urllib.request import urlopen
import ssl

response = urlopen('https://somedomain.co', context=ssl._create_unverified_context())
38
Kron

Pour ceux qui utilisent un ouvre-porte, vous pouvez réaliser la même chose en vous basant sur l'excellente réponse d'Enno Gröper:

import urllib2, ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx), your_first_handler, your_second_handler[...])
opener.addheaders = [('Referer', 'http://example.org/blah.html')]

content = opener.open("https://localhost/").read()

Et puis utilisez-le comme avant.

Selon build_opener et HTTPSHandler , un HTTPSHandler est ajouté si le module ssl est existant, nous spécifions simplement ici notre propre au lieu de celui par défaut.

31
Damien

Selon le message de @Enno Gröper, j'ai essayé le constructeur SSLContext et cela fonctionne bien sur ma machine. code comme ci-dessous:

import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
urllib2.urlopen("https://your-test-server.local", context=ctx)

si vous avez besoin d'ouvreur, ajoutez simplement ce contexte comme:

opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx))

REMARQUE: tout l'environnement de test ci-dessus correspond à python 2.7.12 . J'utilise PROTOCOL_SSLv23 = ici puisque le doc le dit, un autre protocole peut aussi fonctionner mais dépend de votre machine et du serveur distant, veuillez vérifier la doc pour plus de détails.

4
Jkm

Un exemple plus explicite, construit sur le code de Damien (appelle une ressource de test à l'adresse http://httpbin.org/ ). Pour python3. Notez que si le serveur redirige vers une autre URL, uri dans add_password doit contenir la nouvelle URL racine (il est également possible de transmettre une liste d’URL).

import ssl    
import urllib.parse
import urllib.request

def get_resource(uri, user, passwd=False):
    """
    Get the content of the SSL page.
    """
    uri = 'https://httpbin.org/basic-auth/user/passwd'
    user = 'user'
    passwd = 'passwd'

    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE

    password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    password_mgr.add_password(None, uri, user, passwd)

    auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr)

    opener = urllib.request.build_opener(auth_handler, urllib.request.HTTPSHandler(context=context))

    urllib.request.install_opener(opener)

    return urllib.request.urlopen(uri).read()
1
marw