Вопрос по python – Получение токена запроса из API Twitter с помощью Python 3

2

Я пытаюсь использовать Python 3 для взаимодействия с API Twitter, чтобы вернуть ссылку на страницу, которая дает мне пин-код, который можно использовать для запроса токенов доступа. Как подробно здесь:https://dev.twitter.com/docs/auth/pin-based-authorization

API Твиттера отвечает мне, что я не правильно авторизовал свой запрос POST, возвращая 401. Лучше всего предположить, почему я неправильно кодирую подпись HMAC в base64. Все остальные части POST-запроса, которые я генерирую, выглядят корректно на основе примеров правильных POST-запросов, которые я рассмотрел.

Я потратил несколько дней, работая над этим, и я надеюсь, что кто-то может помочь подтолкнуть меня к финальной части.

Вот самые важные части документации по API Twitter: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, которые помогают в разработке для этого. Однако, как опыт обучения, я предпочитаю не использовать их.

Заранее большое спасибо за ваше время и помощь.

Error: User Rate Limit Exceeded James R

Ваш Ответ

2   ответа
0

Convert the HTTP Method to uppercase and set the output string equal to this value. Append the '&' character to the output string. Percent encode the URL and append it to the output string. Append the '&' character to the output string. Percent encode the parameter string and append it to the output string.

Percent encode every key and value that will be signed. Sort the list of parameters alphabetically by encoded key. For each key/value pair: Append the encoded key to the output string. Append the '=' character to the output string. Append the encoded value to the output string. If there are more key/value pairs remaining, append a '&' character to the output string.
Error: User Rate Limit Exceeded Rob S.
9

I swapped out binascii.b2a_base64 for base64.standard_b64encode I converted the bytes to string using the bytes.decode('ascii') method. str() seemed to be appending b to the string. I fixed the order of the parameters to hmac.new - it's KEY, MESSAGE, not MESSAGE, KEY I removed the reference to include_entities in PARAMETER_STRING - if you don't use include_entities in the request (and I believe it doesn't make sense for the token request) it mustn't be included in the PARAMETER_STRING I added oauth_callback=oob to the begin of the PARAMETER_STRING - all oauth parameters except for the oauth_signature must be included in the base string. I changed the section where the request is made to pre-create the Request object, then add the Authorization header - you were sending the Authorization header as the HTTP body. To match this change, I removed the trailing semicolon from HEADER_TITLE. I added the missing semicolon after 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())
Error: User Rate Limit Exceeded Rob S.

Похожие вопросы