Python - 使用Oauth2的SSL问题

时间:2012-02-14 00:40:59

标签: python ssl oauth certificate ssl-certificate

每当尝试在Python中使用oAuth2时,我似乎都遇到了SSL问题。我花了大部分时间试图调试它,但似乎无法弄明白。

这是我的Python脚本(很简单):

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 Interpreter的这些错误:

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 个答案:

答案 0 :(得分:8)

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列表可能已足够。

答案 1 :(得分:7)

首先,运行pip install certifi。然后在发出任何请求之前设置客户端的ca_certs属性:

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

这是受到jterrace建议使用httplib2.Http.add_certificate

的启发

答案 2 :(得分:2)

httplib2附带的默认cacerts.txt包含以下证书:

  • Verisign / RSA安全服务器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 Class 3 Public Primary Certification Authority
  • Verisign Class 1公共主要证书颁发机构 - G2
  • Verisign Class 2公共主要证书颁发机构 - G2
  • Verisign Class 3公共主要认证机构 - G2
  • Verisign Class 4公共主要证书颁发机构 - G2
  • Verisign Class 1公共主要证书颁发机构 - G3
  • Verisign Class 2公共主要证书颁发机构 - G3
  • Verisign Class 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 Primary Root CA
  • VeriSign Class 3公共主要证书颁发机构 - G5
  • Entrust.net安全服务器认证机构
  • 转到Daddy证书颁发机构根证书包

Instagram HTTPS证书由以下人员签署:

  • GeoTrust Global CA

您需要将证书添加到cacerts.txt

答案 3 :(得分:2)

我遇到了与Flask-Social的OAuth调用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")

安装此插件解决了我的问题,没有代码更改/黑客攻击。

答案 4 :(得分:0)

我的系统(OSX Yosemite)上安装了旧版本的Python 2.7(2.7.1)时遇到了同样的错误。

我将Python升级到2.7.10,解决了这个问题。

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

我在尝试不同的解决方案时看到了以下警告信息:

“InsecurePlatformWarning:真正的SSLContext对象不可用。这可以防止urllib3正确配置SSL,并可能导致某些SSL连接失败。有关详细信息,请参阅https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning

答案 5 :(得分:0)

更新cacerts.txt文件的另一种方法是让httplib2保持最新状态。他们偶尔会更新此文件,因此如果您遇到此问题,请检查您是否使用了最新版本的库并进行更新。