谷歌OAuth问题:无效签名
我正在尝试在一个小的Python脚本中实现OAuth功能。我使用的是python-oauth2库,想要连接到谷歌,以便列出我的谷歌文档。
获取请求令牌和授权令牌似乎都没有问题,但每当我尝试获取访问令牌时,都会收到一个HTTP 400的错误响应,内容是“signature_invalid”。
这是我的代码:
import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth
#httplib2.debuglevel=1
# this php script writes oauth_verifier to /tmp/verifier.txt
oauth_callback = 'http://localhost/api.php'
scope = 'https://docs.google.com/feeds/'
xoauth_displayname = 'Adam\'s API Test'
url = 'https://www.google.com/accounts/OAuthGetRequestToken?scope=%s&oauth_callback=%s&xoauth_displayname=%s' % (scope, oauth_callback, xoauth_displayname)
######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous','anonymous')
client = oauth.Client(consumer)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'OAuthGetRequestToken OK'
else:
print 'OAuthGetRequestToken status: %s' % resp['status']
print content
sys.exit(1)
######## OAUTH: AUTHORIZE TOKEN ###############
oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
print 'Visit this URL in your browser: %s' % url
raw_input('Press ENTER once you have granted access...')
######## OAUTH: GET ACCESS TOKEN ##############
verifier = file('/tmp/verifier.txt').read().rstrip()
url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'OAuthGetAccessToken OK'
print content
else:
print 'OAuthGetAccessToken status: %s' % resp['status']
print content
sys.exit(1)
有什么想法吗?
1 个回答
1
在Eva的帮助下,我解决了这个问题!这篇帖子提供了答案.
我没有正确使用从最初请求未授权令牌时返回的 oauth_token_secret
。我忽略了 Consumer
被重复使用,但在获取访问令牌时却为 Client
创建了一个新的实例,这个过程可以在python-oauth2的Twitter三方OAuth示例的README中找到。
下面是修复上述代码的补丁:
--- old.py 2011-07-28 10:38:06.904639958 -0500
+++ new.py 2011-07-28 10:38:44.192639954 -0500
@@ -22,6 +22,7 @@
######## OAUTH: AUTHORIZE TOKEN ###############
oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
+oauth_token_secret = urlparse.parse_qs(content)['oauth_token_secret'][0]
url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
print 'Visit this URL in your browser: %s' % url
raw_input('Press ENTER once you have granted access...')
@@ -29,6 +30,7 @@
######## OAUTH: GET ACCESS TOKEN ##############
verifier = file('/tmp/verifier.txt').read().rstrip()
url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
+client.token = oauth.Token(oauth_token, oauth_token_secret)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'OAuthGetAccessToken OK'
这是应用了补丁后的原始代码:
import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth
#httplib2.debuglevel=1
# this php script writes oauth_verifier to /tmp/verifier.txt
oauth_callback = 'http://localhost/api.php'
scope = 'https://docs.google.com/feeds/'
xoauth_displayname = 'Adam\'s API Test'
url = 'https://www.google.com/accounts/OAuthGetRequestToken?scope=%s&oauth_callback=%s&xoauth_displayname=%s' % (scope, oauth_callback, xoauth_displayname)
######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous','anonymous')
client = oauth.Client(consumer)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'OAuthGetRequestToken OK'
else:
print 'OAuthGetRequestToken status: %s' % resp['status']
print content
sys.exit(1)
######## OAUTH: AUTHORIZE TOKEN ###############
oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
oauth_token_secret = urlparse.parse_qs(content)['oauth_token_secret'][0]
url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
print 'Visit this URL in your browser: %s' % url
raw_input('Press ENTER once you have granted access...')
######## OAUTH: GET ACCESS TOKEN ##############
verifier = file('/tmp/verifier.txt').read().rstrip()
url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
client.token = oauth.Token(oauth_token, oauth_token_secret)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'OAuthGetAccessToken OK'
print content
else:
print 'OAuthGetAccessToken status: %s' % resp['status']
print content
sys.exit(1)
需要注意的是,其实在获取访问令牌时,oauth_token
和 oauth_verifier
不需要手动添加到查询字符串中(python-oauth2会为我们处理这些)。我保留了原始代码,以便展示从不工作的代码到这个答案中的工作代码的最简单变化。最终的URL可以简单写成 https://www.google.com/accounts/OAuthGetAccessToken
。
最后打印的内容会输出 oauth_token
和 oauth_token_secret
。这些参数会在后续的API调用中使用,比如获取Google Docs上的文档列表。
下面是实现这个功能的示例代码:
import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth
######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous', 'anonymous')
creds = {'oauth_token_secret': 'INSERT_SECRET_FROM_ABOVE', 'oauth_token': 'INSERT_TOKEN_FROM_ABOVE'}
client = oauth.Client(consumer)
client.token = oauth.Token(creds['oauth_token'], creds['oauth_token_secret'])
url = 'https://docs.google.com/feeds/default/private/full?v=3'
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
print 'list status OK'
fh = open('/tmp/list.xml', 'w')
fh.write(content)
fh.close()
else:
print 'list status: %s' % resp['status']
print content
sys.exit(1)