Python - Oauth2的SSL问题
我在用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解释器的错误信息:
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 个回答
2
httplib2自带的默认cacerts.txt文件里包含了这些证书:
- Verisign/RSA安全服务器CA
- Thawte个人基础CA
- Thawte个人高级CA
- Thawte个人免费邮件CA
- Thawte服务器CA
- Thawte高级服务器CA
- Equifax安全CA
- Verisign 1级公共根证书颁发机构
- Verisign 2级公共根证书颁发机构
- Verisign 3级公共根证书颁发机构
- Verisign 1级公共根证书颁发机构 - G2
- Verisign 2级公共根证书颁发机构 - G2
- Verisign 3级公共根证书颁发机构 - G2
- Verisign 4级公共根证书颁发机构 - G2
- Verisign 1级公共根证书颁发机构 - G3
- Verisign 2级公共根证书颁发机构 - G3
- Verisign 3级公共根证书颁发机构 - G3
- Verisign 4级公共根证书颁发机构 - G3
- Equifax安全全球电子商务CA
- Equifax安全电子商务CA 1
- Equifax安全电子商务CA 2
- Thawte时间戳CA
- Thawte根证书CA
- VeriSign 3级公共根证书颁发机构 - G5
- Entrust.net安全服务器证书颁发机构
- Go Daddy证书颁发机构根证书包
Instagram的HTTPS证书是由以下机构签发的:
- GeoTrust全球CA
你需要把这个证书添加到你的cacerts.txt文件里。
7
首先,运行 pip install certifi
这个命令。然后,在发起任何请求之前,设置客户端的 ca_certs 属性:
client = oauth.Client(consumer)
client.ca_certs = certifi.where()
这个方法是受到 jterrace 的建议启发,使用了 httplib2.Http.add_certificate
。
9
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列表可能已经足够用了。