web-dev-qa-db-fra.com

urllib et erreur "SSL: CERTIFICATE_VERIFY_FAILED"

Je reçois l'erreur suivante:

Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in        __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in  run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

C'est le code qui cause cette erreur:

if input.startswith("!web"):
    input = input.replace("!web ", "")      
    url = "https://domainsearch.p.mashape.com/index.php?name=" + input
    req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
    info = urllib2.urlopen(req).read()
    Message.Chat.SendMessage ("" + info)

L'API que j'utilise nécessite l'utilisation de HTTPS. Comment puis-je le faire contourner la vérification?

192
user3724476

Si vous juste souhaitez ignorer la vérification, vous pouvez créer un nouveau SSLContext . Par défaut, les contextes nouvellement créés utilisent CERT_NONE .

Soyez prudent avec ceci comme indiqué dans la section 17.3.7.2.1

Lorsque vous appelez directement le constructeur SSLContext, CERT_NONE est la valeur par défaut. Dans la mesure où il n'authentifie pas l'autre homologue, il peut s'avérer peu sûr, en particulier en mode client, où vous souhaitez la plupart du temps garantir l'authenticité du serveur avec lequel vous parlez. Par conséquent, en mode client, il est vivement recommandé d'utiliser CERT_REQUIRED. 

Mais si vous voulez simplement que cela fonctionne maintenant pour une autre raison, vous devez procéder de la manière suivante: import ssl:

input = input.replace("!web ", "")      
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' })
gcontext = ssl.SSLContext()  # Only for gangstars
info = urllib2.urlopen(req, context=gcontext).read()
Message.Chat.SendMessage ("" + info)

Cela devrait résoudre votre problème, mais vous ne résolvez pas vraiment tous les problèmes, mais vous ne verrez pas le [SSL: CERTIFICATE_VERIFY_FAILED] car vous ne vérifiez pas le certificat!

Pour ajouter à ce qui précède, si vous souhaitez en savoir plus sur les raisons de ces problèmes, vous pouvez consulter/ PEP 476 .

Ce PEP propose d'activer la vérification des signatures de certificat X509, ainsi que la vérification du nom d'hôte pour les clients HTTP de Python par défaut, sous réserve d'une option de retrait par appel. Cette modification serait appliquée à Python 2.7, Python 3.4 et Python 3.5. 

Il y a une option de retrait conseillée qui n'est pas différente de mon conseil ci-dessus:

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

Il comporte également une option fortement déconseillée via monkeypatching que vous ne voyez pas souvent en python:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

Ce qui remplace la fonction par défaut pour la création de contexte avec la fonction pour créer un contexte non vérifié.

Veuillez noter ceci comme indiqué dans le PEP:

Ce guide s'adresse principalement aux administrateurs système qui souhaitent adopter des versions plus récentes de Python qui implémentent ce PEP dans des environnements hérités qui ne prennent pas encore en charge la vérification de certificat sur les connexions HTTPS. Par exemple, un administrateur peut choisir de ne pas participer en ajoutant le monkeypatch ci-dessus à sitecustomize.py dans son environnement d'exploitation standard pour Python. Les applications et les bibliothèques NE DEVRAIENT PAS élargir ce processus de modification (sauf peut-être en réponse à un paramètre de configuration contrôlé par l'administrateur système). 

Si vous voulez lire un article sur pourquoi ne pas valider les certificats est mauvais dans le logiciel vous pouvez le trouver ici !

217
Noelkd

Ce n'est pas une solution à votre problème spécifique, mais je le mets ici car ce fil est le premier résultat de Google pour "SSL: CERTIFICATE_VERIFY_FAILED", et il me conduit à la poursuite de l'oie sauvage.

Si vous avez installé Python 3.6 sur OSX et obtenez le message d'erreur "SSL: CERTIFICATE_VERIFY_FAILED" lorsque vous essayez de vous connecter à un site https: //, c'est probablement parce que Python 3.6 sur OSX n'a ​​aucun certificat et ne peut valider aucun certificat SSL. les liaisons. Cette modification de la version 3.6 sous OSX nécessite une étape de post-installation, qui installe le paquet de certificats certifi. Ceci est documenté dans le ReadMe, que vous devriez trouver à /Applications/Python\ 3.6/ReadMe.rtf

Le fichier Lisezmoi vous demandera d’exécuter ce script de post-installation, qui installe simplement certifi: /Applications/Python\ 3.6/Install\ Certificates.command

Les notes de publication contiennent des informations supplémentaires: https://www.python.org/downloads/release/python-360/

246
Craig Glennie

Pour développer la réponse de Craig Glennie (désolé, pas assez de réputation pour commenter):

en Python 3.6.1 sur MacOs Sierra

Entrer cela dans le terminal bash a résolu le problème:

pip install certifi
/Applications/Python\ 3.6/Install\ Certificates.command
47
jnPy

Sous Windows, Python ne regarde pas le certificat système, il utilise son propre répertoire situé à ?\lib\site-packages\certifi\cacert.pem.

La solution à votre problème: 

  1. téléchargez le certificat de validation de domaine en tant que fichier * .crt ou * pem
  2. ouvrez le fichier dans l'éditeur et copiez le contenu dans le presse-papier
  3. trouvez votre cacert.pem emplacement: from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)
  4. éditez le fichier cacert.pem et collez votre certificat de validation de domaine à la fin du fichier.
  5. Enregistrez le fichier et profitez des demandes!
25
Bruno Gabuzomeu

Ma solution pour Mac OS X:

1) Mettez à niveau vers Python 3.6.5 à l’aide du programme d’installation natif de l’application Python téléchargé à partir du site Web officiel du langage Python https://www.python.org/downloads/

J'ai constaté que ce programme d'installation s'occupe de la mise à jour des liens et des liens symboliques pour le nouveau Python bien mieux qu'homebrew. 

2) Installez un nouveau certificat en utilisant "./Install Certificates.command" qui se trouve dans le répertoire Python 3.6 actualisé. 

> cd "/Applications/Python 3.6/"
> Sudo "./Install Certificates.command"
22
Claude COULOMBE

Vous pouvez essayer d'ajouter ceci à vos variables d'environnement:

PYTHONHTTPSVERIFY=0 

Notez que ceci désactivera tout la vérification HTTP est donc un peu une approche de sledgehammer, cependant si la vérification n'est pas requise, cela peut être une solution efficace.

22
Chris Halcrow

J'avais un problème similaire, bien que j'utilisais urllib.request.urlopen dans Python 3.4, 3.5 et 3.6. (Ceci est une partie de l'équivalent Python 3 de urllib2, comme indiqué dans l'en-tête de la page de documentation urllib2 de Python 2 .)

Ma solution était de pip install certifi pour installer certifi , qui a:

... une collection soigneusement organisée de certificats racine permettant de valider la fiabilité des certificats SSL lors de la vérification de l'identité des hôtes TLS.

Ensuite, dans mon code où je venais tout juste de commencer:

import urllib.request as urlrq
resp = urlrq.urlopen('https://foo.com/bar/baz.html')

Je l'ai révisé pour:

import urllib.request as urlrq
import certifi
resp = urlrq.urlopen('https://foo.com/bar/baz.html', cafile=certifi.where())

Si je lis correctement la documentation urllib2.urlopen , elle contient également un argument cafile. Donc, urllib2.urlopen([...], certifi.where()) pourrait également fonctionner pour Python 2.7.

12
hBy2Py
import requests
requests.packages.urllib3.disable_warnings()

import ssl

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Tiré d'ici https://Gist.github.com/michaelrice/a6794a017e349fc65d01

11
Prostak

Comme je l'ai écrit dans un commentaire, ce problème est probablement lié à cette SO réponse

En bref: il existe plusieurs façons de vérifier le certificat. La vérification utilisée par OpenSSL est incompatible avec les certificats racine de confiance que vous avez sur votre système. OpenSSL est utilisé par Python.

Vous pouvez essayer d'obtenir le certificat manquant pour Autorité de certification principale publique de classe 3 de Verisign puis utiliser l'option cafile selon la documentation de Python :

urllib2.urlopen(req, cafile="verisign.pem")
9
Steffen Ullrich

Pour Python 3.4+ on Centos 6/7, Fedora , installez simplement l'autorité de certification approuvée de cette manière:

  1. Copiez le CA.crt dans /etc/pki/ca-trust/source/anchors/
  2. update-ca-trust force-enable
  3. update-ca-trust extract
4
Cherif KAOUA

Je dois ajouter une autre réponse car, tout comme Craig Glennie, je me suis lancé à la poursuite de l'oie sauvage en raison des nombreux messages faisant référence à ce problème sur le Web.

J'utilise MacPorts, et ce que je pensais à l'origine comme un problème de Python était en fait un problème de MacPorts: il n'installe pas de certificat racine avec son installation d'OpenSL. La solution consiste à port install curl-ca-bundle, comme indiqué dans cet article de blog .

3
corwin.amber

Je me bloque à moitié, car j'avais le même problème, sauf que dans mon cas, l'URL que je frappais était valide, le certificat était valide. Ce qui n’était pas valable c’était ma connexion au Web. J'avais échoué à ajouter des détails de proxy dans le navigateur (IE dans ce cas). Cela a empêché le processus de vérification de se dérouler correctement.
Ajouté dans les détails du proxy et mon python était alors très heureux.

2
Ads

Je suis surpris que toutes ces instructions n'aient pas résolu mon problème. Néanmoins, le diagnostic est correct (BTW, j'utilise Mac et Python3.6.1). Donc, pour résumer la bonne partie:

  • Sur Mac, Apple abandonne OpenSSL
  • Python utilise désormais son propre ensemble de certificats racine CA
  • L’installation binaire de Python a fourni un script pour installer le certificat CA Root requis par Python ("/ Applications/Python 3.6/Install Certificates.command").
  • Lisez "/ Applications/Python 3.6/ReadMe.rtf" pour plus de détails.

Pour moi, le script ne fonctionne pas, et toutes ces installations de certifi et openssl ont échoué. Peut-être parce que j'ai plusieurs installations Python 2 et 3, ainsi que de nombreuses virtualenv. À la fin, je dois le réparer à la main.

pip install certifi   # for your virtualenv
mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl
cp -a <your virtualenv>/site-package/certifi/cacert.pem \
  /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/cert.pem

Si cela vous échoue encore. Ensuite, réinstallez OpenSSL.

port install openssl
2
berniey

Comme vous, j'utilise python 2.7 sur mon ancien iMac (OS X 10.6.8), j'ai également rencontré le problème en utilisant urllib2.urlopen: 

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]

Mes programmes fonctionnaient correctement sans problèmes de certificat SSL et soudainement (après le téléchargement des programmes), ils se sont écrasés avec cette erreur SSL.

Le problème était la version de python utilisée:

  1. Pas de problème avec https://www.python.org/downloads et python-2.7.9-macosx10.6.pkg

  2. problème avec celui installé par Outil Homebrew : "brew install python", version située dans/usr/local/bin.

Un chapitre, appelé Certificate verification and OpenSSL [CHANGED for Python 2.7.9], dans /Applications/Python 2.7/ReadMe.rtf explique le problème avec de nombreux détails.

Alors, vérifiez, téléchargez et mettez dans votre PATH la bonne version de python.

2
Thierry Maillard

Essayer

pip install --trusted-Host pypi.python.org nom_package

Cela a fonctionné pour moi. 

1
user3603105

Jeter un coup d'œil à

/ Applications/Python 3.6/Install Certificates.command

Vous pouvez également aller à Applications et cliquer sur Certificates.command

1
Danielle Cohen

Python 2.7.12 (défaut, le 29 juillet 2016, 15:26:22) a corrigé le problème mentionné. Cette information pourrait aider quelqu'un d'autre.

1
caot

Pour ceux qui utilisent mechanize et rencontrent cette question, voici comment appliquer la même technique à une instance de mécanisation Browser:

br = mechanize.Browser()
context = ssl._create_unverified_context()
br.set_ca_data(context=context)
0
Kirkman14

Si vous utilisez vCenter 6, vous devriez plutôt ajouter votre certificat d'autorité de certification vmware de vCenter à la liste des autorités de certification approuvées de votre système d'exploitation. Pour télécharger votre certificat, procédez comme suit

  1. Ouvrez votre navigateur Web.
  2. Accédez à https: //
  3. Dans le coin inférieur droit, cliquez sur le lien Download Trusted Root CA 

Sur Fedora 

  1. décompressez et changez l'extension de .0 à .cer 
  2. Copiez-le dans/etc/pki/ca-trust/source/anchors /
  3. exécutez la commande update-ca-trust.

Liens:

  1. https://virtualizationreview.com/articles/2015/04/02/install-root-self-signed-certificate-vcenter-6.aspx?m=1
  2. http://forums.fedoraforum.org/showthread.php?t=293856
0
nobler1050

Déjà beaucoup de réponses ici, mais nous avons rencontré cela dans un cas très spécifique et avons perdu beaucoup de temps à enquêter, donc en ajoutant encore un autre. Nous l'avons vu dans le cas suivant:

  • Dans un conteneur Debian-Stretch-Slim
  • Python 3.5.3 par défaut easy_install3
  • Pour les certificats LetsEncrypt enregistrés à l'aide de cert-manager dans notre cluster Kubernetes

Les commandes pip3 et openssl ont toutes deux été en mesure de vérifier le certificat et easy_install3 a pu vérifier les autres certificats LetsEncrypt avec succès.

La solution de contournement consistait à générer la dernière version de Python (3.7.3 à l’époque) à partir des sources. Les instructions ici sont détaillées et faciles à suivre.

0
aschmied

Dans mon cas, cette erreur me causait parce que les versions de requests et urllib3 étaient incompatibles, donnant l'erreur suivante lors de l'installation:

ERROR: requests 2.21.0 has requirement urllib3<1.25,>=1.21.1, but you'll have urllib3 1.25 which is incompatible.
pip install 'urllib3<1.25' --force-reinstall

a fait le tour.

0
fabio.sang

En python 2.7, ajouter les détails de l'autorité de certification racine approuvée à la fin du fichier C:\Python27\lib\site-packages\certifi\cacert.pem

après cela, j'ai exécuté (avec les droits d'administrateur) pip install

0
MD5

Pour Linux Python3.6, cela a fonctionné pour moi.

depuis la ligne de commande, installez pyopenssl et certifi

Sudo pip3 install -U pyopenssl
Sudo pip3 install certifi

et dans mon script python3, ajouté verify = '/ usr/lib/python3.6/site-packages/certifi/cacert.pem' ainsi:

import requests
from requests.auth import HTTPBasicAuth
import certifi

auth = HTTPBasicAuth('username', 'password')
body = {}

r = requests.post(url='https://your_url.com', data=body, auth=auth, verify='/usr/lib/python3.6/site-packages/certifi/cacert.pem')
0
Joe Jadamec

Python 2.7 sur Amazon EC2 avec centOS 7

Je devais définir la variable env SSL_CERT_DIR pour qu'elle pointe vers mon ca-bundle situé à /etc/ssl/certs/ca-bundle.crt

0
Brian McCall

J'ai trouvé ceci sur ici

J'ai trouvé cette solution, insérez ce code au début de votre fichier source:

import ssl

try:
   _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

Ce code annule la vérification afin que la certification SSL ne soit pas vérifiée.

installation des étapes pour nltk (j’avais déjà python3 (3.6.2) installé dans MAC OS X

Sudo easy_install pip

utiliser l'option Ignorer les installations pour ignorer la désinstallation de la version précédente de six

Sudo pip3 install -U nltk --ignore-installed six

Vérifiez l'installation de pip et python, utilisez les versions '3'

which python python2 python3
which pip pip2 pip3

Vérifier si NLTK est installé

python3
import nltk
nltk.__path__
['/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/nltk']

Installez le certificat SSL avant d'installer le livre d'exemples, sinon nous aurons une erreur de certificat lors de l'installation des exemples

/Applications/Python\ 3.6/Install\ Certificates.command
python3 -m nltk.downloader book

L'installation de nltk et nltk_ata pour des exemples de livre a été effectuée avec succès.

0
Narasimha Sai

Solution pour Anaconda

Ma configuration est Anaconda Python 3.7 sur MacOS avec un proxy. Les chemins sont différents.

  • Voici comment vous obtenez le chemin correct certificates:
import ssl
ssl.get_default_verify_paths()

qui sur mon système produit

Out[35]: DefaultVerifyPaths(cafile='/miniconda3/ssl/cert.pem', capath=None,
 openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/miniconda3/ssl/cert.pem',
 openssl_capath_env='SSL_CERT_DIR', openssl_capath='/miniconda3/ssl/certs')

Une fois que vous savez où se trouve le certificat, vous concatérez le certificat utilisé par le proxy à la fin de ce fichier.

J'avais déjà configuré conda pour travailler avec mon proxy en lançant:

conda config --set ssl_verify <pathToYourFile>.crt

Si vous ne vous rappelez pas où se trouve votre certificat, vous pouvez le trouver dans ~/.condarc:

ssl_verify: <pathToYourFile>.crt

Maintenant, concaténer} _ ce fichier à la fin de /miniconda3/ssl/cert.pem et les demandes devraient fonctionner, et en particulier sklearn.datasets et des outils similaires devraient fonctionner.

Autres mises en garde

Les autres solutions n'ont pas fonctionné car la configuration d'Anaconda est légèrement différente:

  • Le chemin Applications/Python\ 3.X n'existe tout simplement pas.

  • Le chemin fourni par les commandes ci-dessous est leMAUVAISchemin

from requests.utils import DEFAULT_CA_BUNDLE_PATH
DEFAULT_CA_BUNDLE_PATH
0
Leo

Installer PyOpenSSL en utilisant pip a fonctionné pour moi (sans conversion en PEM):

pip install PyOpenSSL
0
averma93

J'ai eu ce problème résolu en fermant Fiddler (un proxy de débogage HTTP), vérifiez si un proxy est activé et essayez à nouveau. 

0
vperezb

L'installation de certifi sur Mac a résolu mon problème:

pip install certifi
0
Snehal Parmar

Une autre solution d'Anaconda. J'obtenais CERTIFICATE_VERIFY_FAILED dans mon environnement Python 2.7 sous macOS. Il s'avère que les chemins conda étaient mauvais:

environnement de base (3.7):

>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile='/usr/local/anaconda3/ssl/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/ssl/certs')

2.7 environnement (les chemins n'existaient pas!):

DefaultVerifyPaths(cafile='', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/envs/py27/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/envs/py27/ssl/certs')

Le correctif:

cd /usr/local/anaconda3/envs/py27/
mkdir ssl
cd ssl
ln -s ../../../ssl/cert.pem
0
Peter Tseng