从Twitter的API获取请求令牌与Python 3
我试图使用Python 3与Twitter的API接口返回链接页面,让我一个PIN码,用来请求访问令牌。详细在这里:https://dev.twitter.com/docs/auth/pin-based-authorization从Twitter的API获取请求令牌与Python 3
Twitter的API响应我告诉我,我没有通过返回401正确授权我的POST请求。我最好的猜测是为什么我没有正确编码base64中的HMAC签名。根据我看过的正确的POST请求示例,我生成的POST请求的其他部分显示正确。
我花了好几天这方面的工作,我希望有人能帮助我轻移过去的最后一部分。
以下是Twitter的API文档的最相关的部分:https://dev.twitter.com/docs/api/1/post/oauth/request_token
https://dev.twitter.com/docs/auth/authorizing-request
这是我使用的代码:
import urllib.parse, urllib.request, json
from hashlib import sha1
import hmac
import binascii
import time
import random
import sys
#Server Links
REQUEST_URL = "https://api.twitter.com/oauth/request_token";
ACCESS_URL = "https://api.twitter.com/oauth/access_token";
AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
#Consumer keys
TOKEN = "Omitted"
TOKEN_SECRET = "Omitted"
#Access keys
ACCESS_TOKEN = ""
ACCESS_TOKEN_SECRET = ""
TWEET = ""
count = 1
while len(sys.argv) > count:
TWEET += sys.argv[count] + " "
count += 1
TWEET = TWEET[:-1] #Get rid of trailing space
print(TWEET + "\n")
#Build content header for POST to return request tokens
HEADER_TITLE = "Authorization:"
#Consumer key
HEADER = 'OAuth oauth_callback="oob" oauth_consumer_key="' + TOKEN + '", '
#Nonce
HEADER += 'oauth_nonce="'
NONCE = ""
for i in range(32):
NONCE += chr(random.randint(97, 122))
HEADER += NONCE
HEADER += '", '
#Timestamp
TIMESTAMP = str(int(time.time()))
#Signature
HEADER += 'oauth_signature="'
PARAMETER_STRING = "include_entities=true&oauth_consumer_key=" + TOKEN + "&oauth_nonce=" + NONCE + "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" + TIMESTAMP + "&oauth_version=1.0"
BASE_STRING = 'POST&' + urllib.parse.quote(REQUEST_URL, '') + '&' + urllib.parse.quote(PARAMETER_STRING, '')
SIGNING_KEY = urllib.parse.quote(TOKEN_SECRET, '') + '&'
print("DEBUG : SIGNING KEY " + SIGNING_KEY + " BASE STRING " + BASE_STRING + "\n")
HEADER += str(binascii.b2a_base64(hmac.new(BASE_STRING.encode(), SIGNING_KEY.encode(), sha1).digest()[:-1]))#Note to self, we may not want to remove the last character...
HEADER += '", '
#Signature Method
HEADER += 'oauth_signature_method="HMAC-SHA1", '
#Timestamp
HEADER += 'oauth_timestamp="' + TIMESTAMP + '", '
#Version
HEADER += 'oauth_version="1.0"'
print(HEADER_TITLE + "\n" + HEADER)
print(urllib.request.urlopen(urllib.request.Request(REQUEST_URL, bytes(HEADER_TITLE+HEADER, 'utf-8'))).read())
最后,我想指出,我我意识到Python OAuth和Twitter模块的存在,它们有助于开发此模块。但是,作为一种学习体验,我选择不使用它们。
预先感谢您对我付出的时间和帮助。
的什么我改变的概述:
- 我为
base64.standard_b64encode
- 换出
binascii.b2a_base64
我使用bytes.decode('ascii')
方法转换的字节串。 str()似乎将b附加到字符串。 - 我固定的参数以
hmac.new
- 这是KEY, MESSAGE
,不MESSAGE, KEY
- 我
PARAMETER_STRING
删除的参考include_entities
- 如果你不要求使用include_entities(我相信这没有意义对于令牌请求),它不能包含在PARAMETER_STRING中 - 我将
oauth_callback=oob
添加到PARAMETER_STRING
的开头 - 除了oauth_signature之外的所有oauth参数都必须包含在基本字符串中。 - 我改变了请求的部分来预先创建Request对象,然后添加Authorization头部 - 您将Authorization头部作为HTTP主体发送。
- 要匹配此更改,我从
HEADER_TITLE
中删除了尾随分号。 - 我在
oauth_callback="oob"
后添加了缺少的分号。
享受!
这是你的代码的固定版本:
import urllib.parse, urllib.request, json
from hashlib import sha1
import hmac
import base64
import time
import random
import sys
#Server Links
REQUEST_URL = "https://api.twitter.com/oauth/request_token";
ACCESS_URL = "https://api.twitter.com/oauth/access_token";
AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
#Consumer keys
TOKEN = "Omitted"
TOKEN_SECRET = "Omitted"
#Access keys
ACCESS_TOKEN = ""
ACCESS_TOKEN_SECRET = ""
TWEET = ""
count = 1
while len(sys.argv) > count:
TWEET += sys.argv[count] + " "
count += 1
TWEET = TWEET[:-1] #Get rid of trailing space
print(TWEET + "\n")
#Build content header for POST to return request tokens
HEADER_TITLE = "Authorization"
#Consumer key
HEADER = 'OAuth oauth_callback="oob", oauth_consumer_key="' + TOKEN + '", '
#Nonce
HEADER += 'oauth_nonce="'
NONCE = ""
for i in range(32):
NONCE += chr(random.randint(97, 122))
HEADER += NONCE
HEADER += '", '
#Timestamp
TIMESTAMP = str(int(time.time()))
#Signature
HEADER += 'oauth_signature="'
PARAMETER_STRING = "oauth_callback=oob&oauth_consumer_key=" + TOKEN + "&oauth_nonce=" + NONCE + "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" + TIMESTAMP + "&oauth_version=1.0"
BASE_STRING = 'POST&' + urllib.parse.quote(REQUEST_URL, '') + '&' + urllib.parse.quote(PARAMETER_STRING, '')
SIGNING_KEY = urllib.parse.quote(TOKEN_SECRET, '') + '&'
print("DEBUG : SIGNING KEY " + SIGNING_KEY + " BASE STRING " + BASE_STRING + "\n")
HEADER += urllib.parse.quote(base64.standard_b64encode(hmac.new(SIGNING_KEY.encode(), BASE_STRING.encode(), sha1).digest()).decode('ascii'))
HEADER += '", '
#Signature Method
HEADER += 'oauth_signature_method="HMAC-SHA1", '
#Timestamp
HEADER += 'oauth_timestamp="' + TIMESTAMP + '", '
#Version
HEADER += 'oauth_version="1.0"'
print(HEADER_TITLE + ":\n" + HEADER)
HTTP_REQUEST = urllib.request.Request(REQUEST_URL)
HTTP_REQUEST.add_header(HEADER_TITLE, HEADER)
print(urllib.request.urlopen(HTTP_REQUEST, bytes('', 'ascii')).read())
干得好,反应非常透彻。非常感谢你。在五小时时限到来的时候,我会奖励赏金。 – 2012-04-15 16:37:24
看起来不像你的签名基本字符串是正确的。基本上,就我所见,您不在基本字符串中包含任何参数。
上签名碱串的主题To quote the twitter docs:
- 转换的HTTP方法为大写和设置输出字符串等于这个值。
- 将'&'字符附加到输出字符串。
- Percent对URL进行编码并将其附加到输出字符串。
- 将'&'字符附加到输出字符串。
- 百分比编码参数字符串并将其附加到输出字符串。
参数字符串反过来又使这样的:(和我引述):
- 百分比编码每一个关键,而将签署价值。
- 按编码密钥按字母顺序对参数列表进行排序。
- 对于每个键/值对:
- 附加编码键码来输出字符串。
- 追加'='字符到输出字符串。
- 将编码后的值附加到输出字符串。
- 如果存在剩余的多个键/值对,追加一个“&”字符到所述输出字符串。
感谢您的回复。我已更新我的代码以将参数字符串追加到基本字符串,但它仍然不起作用。我想知道你是否不介意再看一眼呢? :) – 2012-04-14 21:36:39
是否已确认这包Python3K的作品? – 2012-04-10 00:21:45