从检索Twitter的API请求令牌与Python 3(Retrieving a Request T

2019-06-23 11:53发布

我试图使用Python 3与Twitter的API接口返回链接页面,让我一个PIN码,用来请求访问令牌。 由于这里详细: https://dev.twitter.com/docs/auth/pin-based-authorization

Twitter的API回应我,告诉我,我还没有正确地返回一个401我最好的猜测,这是为什么我不正确编码以base64的HMAC签名授权我POST请求。 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的模块,其帮助开发这种存在。 然而,作为一个学习的经验,我选择不使用它们。

非常感谢你提前为您的时间和帮助。

Answer 1:

是什么改变了我的概述:

  1. 我换出binascii.b2a_base64base64.standard_b64encode
  2. 我使用变换后的字节串bytes.decode('ascii')方法。 STR()似乎被附加b键的字符串。
  3. 我固定的参数以hmac.new -这是KEY, MESSAGE ,没有MESSAGE, KEY
  4. 我删除了参考include_entitiesPARAMETER_STRING -如果你不要求使用include_entities(我相信它不会使令牌请求检测)它必须不被列入PARAMETER_STRING
  5. 我添加oauth_callback=oob到的开始PARAMETER_STRING -除了oauth_signature所有的OAuth参数必须被包括在基底线上。
  6. 我改变了该请求是由预先创建的Request对象,然后添加Authorization头部分 - 你发送的授权头作为HTTP主体。
  7. 为了配合这种变化,我删除从尾随分号HEADER_TITLE
  8. 我加入后失踪分号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())


Answer 2:

不像你的签名基本字符串是正确的。 基本上,你不包括在基础线的任何参数,只要我能看到。

引述Twitter的文档上签字基底线的话题:

  1. 转换的HTTP方法为大写和设置输出字符串等于这个值。
  2. 追加“&”字符输出字符串。
  3. 百分比编码的URL并将其追加到输出字符串。
  4. 追加“&”字符输出字符串。
  5. 百分比编码参数字符串,并将其追加到输出字符串。

参数字符串反过来又使这样的:(和我引述):

  1. 百分比编码每个键和值将被签署。
  2. 按字母顺序编码的关键排序参数列表。
  3. 对于每个键/值对:
  4. 追加编码的关键输出字符串。
  5. 追加“=”字符到所述输出字符串。
  6. 附加编码的值,以输出字符串。
  7. 如果有更多的键/值对剩余的,附加一个“&”字符到所述输出字符串。


文章来源: Retrieving a Request Token from the Twitter API with Python 3