2012-02-14 32 views
13

Parece que tengo un problema con SSL cuando intento usar oAuth2 en Python. He pasado la mayor parte de la tarde intentando depurarlo pero parece que no puedo resolverlo.Python - Problema SSL con Oauth2

Aquí está mi script Python (bonito y sencillo):

import oauth2.oauth2 as oauth 
import urlparse 
import time 

## If you're actually processing requests, you'll want this 
# import simplejson 


### GET A REQUEST TOKEN ### 

consumer = oauth.Consumer(key="***KEYHERE***", secret="***KEYSECRETHERE***") 

request_token_url = 'https://api.instagram.com/oauth/access_token' 

client = oauth.Client(consumer) 
resp, content = client.request(request_token_url, "GET") 

request_token = dict(urlparse.parse_qsl(content)) 


token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret']) 

Y estos errores desde el intérprete de Python:

Traceback (most recent call last): 
    File "E:\Projects\oAuth2Test\test.py", line 16, in <module> 
    resp, content = client.request(request_token_url, "GET") 
    File "E:\Projects\oAuth2Test\oauth2\oauth2.py", line 682, in request 
    connection_type=connection_type) 
    File "E:\Projects\oAuth2Test\httplib2\httplib2.py", line 1445, in request 
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) 
    File "E:\Projects\oAuth2Test\httplib2\httplib2.py", line 1197, in _request 
    (response, content) = self._conn_request(conn, request_uri, method, body, headers) 
    File "E:\Projects\oAuth2Test\httplib2\httplib2.py", line 1133, in _conn_request 
    conn.connect() 
    File "E:\Projects\oAuth2Test\httplib2\httplib2.py", line 914, in connect 
    raise SSLHandshakeError(e) 
SSLHandshakeError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 

Ahora, sólo por lo que se sabe, tengo mi cacerts.txt que vino con httplib2 en el lugar correcto y se encuentra, sin embargo, todavía tengo este problema. Cualquier ayuda es apreciada, gracias!

Respuesta

8

cacerts.txt contiene muy pocos CA. Si lo reemplaza con cacert.pem, entonces no hay error ssl. Aquí hay un script de prueba:

#!/usr/bin/env python3 
import http.client 
import ssl 

####context = ssl.create_default_context(cafile='cacerts.txt') # ssl.SSLError 
####context = ssl.create_default_context(cafile='cacert.pem') # works 
context = ssl.create_default_context() # works as is on the recent versions 
#NOTE: ssl.CERT_REQUIRED is set for the default Purpose.SERVER_AUTH 

h = http.client.HTTPSConnection('api.instagram.com', 443, context=context) 
h.request('POST', '/oauth/access_token') 
resp = h.getresponse() 
print(resp.status, resp.reason) # produce expected 400 http error 
print(resp.headers) 
print(resp.read()) 

Como el ejemplo demuestra, la lista de CA por defecto podría ser suficiente en las últimas versiones de software.

+0

Este 'cacerts.pem' parece mucho más completo. Enlace útil. –

+1

Como un truco rápido también puede sobrescribir los cacerts.txt con los cacerts.arriba, la desventaja es que debes asegurarte de que esto se haga en todos tus virtualenv, por lo que no es realmente ideal. – Damian

2

El cacerts.txt defecto que viene con httplib2 contiene estos certificados:

  • Verisign/RSA Secure servidor de CA
  • Thawte personal básica CA
  • Thawte Premium Personal CA
  • Thawte Freemail Personal CA
  • Thawte Server CA
  • Thawte Premium Server CA
  • Equifax Secure CA
  • Verisign Class 1 Autoridad de Certificación Primaria Pública
  • certificado Clase 2 Autoridad de Certificación Primaria Pública
  • Verisign Class 3 Autoridad de Certificación Primaria Pública
  • Verisign Class 1 Autoridad de Certificación Primaria Pública - G2
  • Verisign Class 2 Public Primary Certification Authority - G2
  • Verisign Class 3 Public Primary Certification Authority - G2
  • Veri signo Clase 4 Autoridad de Certificación Primaria Pública - G2
  • Verisign Class 1 Public Autoridad de Certificación Primaria - G3
  • 2 Autoridad de Certificación Primaria Pública
  • Verisign Class - G3
  • Verisign Class 3 Autoridad de Certificación Primaria Pública - G3
  • Verisign Class 4 Pública Autoridad de Certificación primaria - G3
  • Equifax Secure Global eBusiness CA
  • Equifax Secure eBusiness CA 1
  • Equifax Secure eBusiness CA 2
  • Thawte Sellado de Tiempo CA
  • thawte raíz primaria CA
  • clase 3 de VeriSign Pública Autoridad de Certificación Primaria - G5
  • Entrust.Certificación red Servidor Seguro Autoridad
  • Certificación Go Daddy Autoridad de Certificación Raíz paquete certificado HTTPS

El instagram está firmado por:

  • GeoTrust Global CA

Usted tendrá que añadir el certificado a su cacerts.txt

+0

He encontrado los detalles del certificado, pero ¿cómo puedo obtener oauth2 para leer un archivo cacerts.txt diferente? – Steve

+0

El objeto oauth2 '' Client'' hereda de '' httplib2.Http'', por lo que debe llamar a su [add_certificate] (http://httplib2.googlecode.com/hg/doc/html/libhttplib2.html#httplib2. Método Http.add_certificate). – jterrace

7

Primero, ejecute pip install certifi. A continuación, establezca la propiedad ca_certs del cliente, antes de solicitar:

client = oauth.Client(consumer) 
client.ca_certs = certifi.where() 

Esto fue inspirada por la sugerencia de jterrace utilizar httplib2.Http.add_certificate

2

yo estaba corriendo en el mismo problema con la llamada de OAuth del frasco-Social a Facebook. La solución más fácil es instalar el complemento httplib2.ca_certs_locator.

En httplib2. init .py, hay una comprobación incorporada para cargar certificados de otra fuente en lugar del archivo cacerts.txt proporcionada con la biblioteca:

try: 
    # Users can optionally provide a module that tells us where the CA_CERTS 
    # are located. 
    import ca_certs_locater 
    CA_CERTS = ca_certs_locater.get() 
except ImportError: 
    # Default CA certificates file bundled with httplib2. 
    CA_CERTS = os.path.join(
     os.path.dirname(os.path.abspath(__file__)), "cacerts.txt") 

La instalación de este plug-in solucionado el problema para mí sin cambios de código/hack-a-rounds.

+0

Tenga en cuenta que las versiones anteriores de httplib2 no intentan cargar desde 'ca_certs_locator' –

0

Estaba teniendo el mismo error en mi sistema (OSX Yosemite) que tenía una versión anterior de Python 2.7 instalada (2.7.1).

Actualicé Python a 2.7.10, lo que resolvió el problema.

https://www.python.org/downloads/release/python-2710/

La clave estaba en el mensaje de advertencia que vi mientras estaba experimentando con diferentes soluciones:

"InsecurePlatformWarning: Un verdadero objeto SSLContext no está disponible Esto evita urllib3 de la configuración de SSL adecuadamente. y puede hacer que fallen ciertas conexiones SSL. Para obtener más información, consulte https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning "

0

Una forma más de actualizar su archivo cacerts.txt es mantener al día. De vez en cuando actualizan este archivo, por lo que si se encuentra con este problema, verifique si no está utilizando la última versión de la biblioteca y actualícela.