urllib y error "SSL: CERTIFICATE_VERIFY_FAILED"

Resuelto user3724476 asked hace 9 años • 48 respuestas

Estoy teniendo el siguiente error:

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)>

Este es el código que está causando este error:

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)

La API que estoy usando requiere que use HTTPS. ¿Cómo puedo hacer para evitar la verificación?

user3724476 avatar Jan 08 '15 15:01 user3724476
Aceptado

Esta no es una solución a su problema específico, pero la pongo aquí porque este hilo es el resultado principal de Google para "SSL: CERTIFICATE_VERIFY_FAILED", y me lleva a una búsqueda inútil.

Si instaló Python 3.6 en OSX y recibe el error "SSL: CERTIFICATE_VERIFY_FAILED" al intentar conectarse a un sitio https://, probablemente se deba a que Python 3.6 en OSX no tiene ningún certificado y no puede validar ningún SSL. conexiones. Este es un cambio para 3.6 en OSX y requiere un paso posterior a la instalación, que instala el certifipaquete de certificados. Esto está documentado en el archivo ReadMe.rtf , que puede encontrar en /Applications/Python\ 3.6/ReadMe.rtf(consulte también el archivo Conclusion.rtf y el script build-installer.pyque genera el instalador de macOS).

El archivo Léame le permitirá ejecutar el script posterior a la instalación en

/Applications/Python\ 3.10/Install\ Certificates.command(Aplicación Terminal, este comando por sí solo debería solucionar el problema. Asegúrese de actualizar la ruta del archivo usando su subversión actual).

(su fuente es install_certificates.command), que:

  • primero instala el paquete Pythoncertifi y
  • luego crea un enlace simbólico desde el archivo de certificados OpenSSL al archivo de certificados instalado por el paquete certifi.

Las notas de la versión tienen más información: https://www.python.org/downloads/release/python-360/

En las versiones más recientes de Python, hay más documentación sobre esto:

  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/resources/ReadMe.rtf#L22-L34
  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/resources/Conclusion.rtf#L15-L19
  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/resources/Welcome.rtf#L23-L25
  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/resources/install_certificates.command
  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/README.rst
  • https://github.com/python/cpython/blob/e05a703848473b0365886dcc593cbddc46609f29/Mac/BuildScript/build-installer.py#L239-L246
Craig Glennie avatar Feb 19 '2017 23:02 Craig Glennie

Si solo desea omitir la verificación, puede crear un nuevo SSLContext . De forma predeterminada, los contextos recién creados utilizan CERT_NONE .

Tenga cuidado con esto como se indica en el apartado 17.3.7.2.1

Al llamar directamente al constructor SSLContext, CERT_NONE es el valor predeterminado. Dado que no autentica al otro par, puede ser inseguro, especialmente en el modo cliente, donde la mayoría de las veces desea garantizar la autenticidad del servidor con el que está hablando. Por lo tanto, cuando esté en modo cliente, se recomienda encarecidamente utilizar CERT_REQUIRED.

import sslPero si sólo quieres que funcione ahora por algún otro motivo, puedes hacer lo siguiente, también tendrás que hacerlo :

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)

Esto debería solucionar su problema, pero en realidad no está resolviendo ninguno de los problemas, ¡pero no verá el certificado [SSL: CERTIFICATE_VERIFY_FAILED]porque ahora no está verificando el certificado!

Además de lo anterior, si desea saber más sobre por qué ve estos problemas, querrá consultar PEP 476 .

Este PEP propone habilitar la verificación de firmas de certificados X509, así como la verificación del nombre de host para los clientes HTTP de Python de forma predeterminada, sujeto a exclusión voluntaria por llamada. Este cambio se aplicaría a Python 2.7, Python 3.4 y Python 3.5.

Existe una opción de exclusión recomendada que no es diferente a mi consejo anterior:

import ssl

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

También presenta una opción muy desaconsejada mediante el parcheo de monos que no se ve a menudo en Python:

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

Lo que anula la función predeterminada para la creación de contexto con la función para crear un contexto no verificado.

Tenga en cuenta con esto como se indica en el PEP:

Esta guía está dirigida principalmente a administradores de sistemas que deseen adoptar versiones más nuevas de Python que implementen este PEP en entornos heredados que aún no admiten la verificación de certificados en conexiones HTTPS. Por ejemplo, un administrador puede optar por no participar agregando el parche de mono anterior a sitecustomize.py en su entorno operativo estándar para Python. Las aplicaciones y bibliotecas NO DEBEN hacer que este proceso de cambio sea amplio (excepto quizás en respuesta a una configuración controlada por el administrador del sistema).

Si desea leer un artículo sobre por qué no validar certificados es malo en el software, puede encontrarlo aquí .

Noelkd avatar Jan 20 '2015 18:01 Noelkd

Para ampliar la respuesta de Craig Glennie:

en Python 3.6.1 en MacOs Sierra

Ingresar esto en la terminal bash resolvió el problema:

pip install certifi
/Applications/Python\ 3.6/Install\ Certificates.command
jnPy avatar Jul 10 '2017 17:07 jnPy

En Windows, Python no mira el certificado del sistema, utiliza el suyo propio ubicado en ?\lib\site-packages\certifi\cacert.pem.

La solución a tu problema:

  1. descargue el certificado de validación del dominio como archivo *.crt o *pem
  2. abra el archivo en el editor y copie su contenido al portapapeles
  3. encuentra tu cacert.pemubicación:from requests.utils import DEFAULT_CA_BUNDLE_PATH; print(DEFAULT_CA_BUNDLE_PATH)
  4. edite el cacert.pemarchivo y pegue su certificado de validación de dominio al final del archivo.
  5. ¡Guarde el archivo y disfrute de las solicitudes!
Bruno Gabuzomeu avatar Aug 10 '2015 08:08 Bruno Gabuzomeu