Python - проблема SSL с Oauth2
Кажется, у меня возникают проблемы с SSL всякий раз, когда я пытаюсь использовать oAuth2 в Python. Я провел большую часть дня, пытаясь отладить его, но, похоже, не могу понять это.
Вот мой Python Script (красивый и простой):
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'])
И эти ошибки от интерпретатора 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
Теперь, чтобы было известно, у меня есть файл cacerts.txt, который поставляется с httplib2 в нужном месте, и он найден, но у меня все еще есть эта проблема. Любая помощь приветствуется, спасибо!
6 ответов
cacerts.txt
содержит слишком мало CA. Если вы замените его на cacert.pem, то ошибки ssl не будет. Вот тестовый скрипт:
#!/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())
Как показано в примере, список CA по умолчанию может быть достаточно для последних версий программного обеспечения.
Первый забег pip install certifi
, Затем установите клиентское свойство ca_certs, прежде чем делать какие-либо запросы:
client = oauth.Client(consumer)
client.ca_certs = certifi.where()
Это было вдохновлено предложением Jterrace использовать httplib2.Http.add_certificate
Я столкнулся с той же проблемой, связанной с OAuth-звонком Flask-Social в Facebook. Самое простое решение - установить плагин httplib2.ca_certs_locator.
В httplib2.init.py, есть встроенная проверка для загрузки сертификатов из другого источника вместо файла cacerts.txt, поставляемого с библиотекой:
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")
Установка этого плагина устранила проблему для меня без каких-либо изменений кода / взлома.
Файл cacerts.txt по умолчанию, поставляемый с httplib2, содержит следующие сертификаты:
- Verisign / RSA Secure Server CA
- Thawte Personal Basic CA
- Thawte Personal Premium CA
- Thawte Personal Freemail CA
- Thawte Server CA
- Thawte Premium Server CA
- Equifax Secure CA
- Государственный первичный центр сертификации Verisign Class 1
- Государственный первичный центр сертификации Verisign Class 2
- Государственный первичный центр сертификации Verisign класса 3
- Государственный первичный центр сертификации Verisign Class 1 - G2
- Государственный первичный центр сертификации Verisign Class 2 - G2
- Государственный первичный центр сертификации Verisign класса 3 - G2
- Государственный первичный центр сертификации Verisign Class 4 - G2
- Государственный первичный центр сертификации Verisign Class 1 - G3
- Государственный первичный центр сертификации Verisign Class 2 - G3
- Государственный первичный центр сертификации Verisign класса 3 - G3
- Государственный первичный центр сертификации Verisign Class 4 - G3
- Equifax Secure Global eBusiness CA
- Equifax Secure eBusiness CA 1
- Equifax Secure eBusiness CA 2
- Thawte Time Stamping CA
- thawte первичный корень CA
- Государственный первичный центр сертификации VeriSign класса 3 - G5
- Entrust.net безопасный центр сертификации серверов
- Пакет корневых сертификатов Go Daddy Certification Authority
HTTPS сертификат instagram подписывается:
- GeoTrust Global CA
Вам нужно будет добавить сертификат в ваш cacerts.txt
Еще один способ обновить свой cacerts.txt
файл хранить httplib2
до настоящего времени. Они иногда обновляют этот файл, поэтому, если вы столкнулись с этой проблемой, проверьте, не используете ли вы последнюю версию библиотеки, и обновите ее.
У меня была такая же ошибка в моей системе (OSX Yosemite), на которой была установлена старая версия Python 2.7 (2.7.1).
Я обновил Python до 2.7.10, что решило проблему.
https://www.python.org/downloads/release/python-2710/
Подсказка была в следующем предупреждающем сообщении, которое я увидел, когда экспериментировал с различными решениями:
"InsecurePlatformWarning: настоящий объект SSLContext недоступен. Это препятствует правильной настройке SSL urllib3 и может привести к сбою некоторых SSL-соединений. Для получения дополнительной информации см. https://urllib3.readthedocs.org/en/latest/security.html