使用 Python 3 从 Twitter API 检索请求令牌 [英] Retrieving a Request Token from the Twitter API with Python 3

查看:58
本文介绍了使用 Python 3 从 Twitter API 检索请求令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Python 3 与 Twitter API 交互以返回页面的链接,该链接为我提供了用于请求访问令牌的 PIN 码.如此处详述:https://dev.twitter.com/docs/auth/pin-基于授权

I am attempting to use Python 3 to interface with the Twitter API to return the link for a page that gives me a pin number to use to request access tokens. As detailed here: https://dev.twitter.com/docs/auth/pin-based-authorization

Twitter 的 API 回复我,告诉我我没有通过返回 401 正确授权我的 POST 请求.我最好的猜测是我没有正确编码 base64 中的 HMAC 签名.根据我查看过的正确 POST 请求示例,我生成的 POST 请求的所有其他部分都是正确的.

Twitter's API responds to me telling me that I have not properly authorized my POST request by returning a 401. My best guess as to why is that I'm not encoding the HMAC signature in base64 correctly. Everything other part of the POST request I generate appears correct based on samples of correct POST requests I have looked at.

我已经花了几天的时间来研究这个,我希望有人能帮助我完成最后一部分.

I have spent several days working on this and I am hoping someone can help nudge me past the final part.

以下是 Twitter API 文档中最相关的部分:https://dev.twitter.com/docs/api/1/post/oauth/request_token

Here are the most relevant parts of the Twitter API docs: 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 模块的存在,它们有助于为此进行开发.但是,作为学习经验,我选择不使用它们.

Finally, I would like to note that I am aware of the existence of Python OAuth and Twitter modules which aid in development for this. However, as a learning experience, I am choosing not to use them.

非常感谢您的时间和帮助.

Thank you very much in advance for your time and assistance.

推荐答案

我所做更改的概述:

  1. 我将 binascii.b2a_base64 换成了 base64.standard_b64encode
  2. 我使用 bytes.decode('ascii') 方法将字节转换为字符串.str() 似乎将 b 附加到字符串.
  3. 我将参数的顺序固定为 hmac.new - 它是 KEY, MESSAGE,而不是 MESSAGE, KEY
  4. 我删除了 PARAMETER_STRING 中对 include_entities 的引用 - 如果您不在请求中使用 include_entities(我认为这对令牌请求没有意义) 它不得包含在 PARAMETER_STRING
  5. 我在 PARAMETER_STRING 的开头添加了 oauth_callback=oob - 除了 oauth_signature 之外的所有 oauth 参数都必须包含在基本字符串中.
  6. 我更改了发出请求的部分,以预先创建 Request 对象,然后添加 Authorization 标头 - 您将 Authorization 标头作为 HTTP 正文发送.
  7. 为了配合这一变化,我从 HEADER_TITLE 中删除了结尾的分号.
  8. 我在 oauth_callback="oob" 之后添加了缺少的分号.
  1. I swapped out binascii.b2a_base64 for base64.standard_b64encode
  2. I converted the bytes to string using the bytes.decode('ascii') method. str() seemed to be appending b to the string.
  3. I fixed the order of the parameters to hmac.new - it's KEY, MESSAGE, not MESSAGE, KEY
  4. 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
  5. 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.
  6. 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.
  7. To match this change, I removed the trailing semicolon from HEADER_TITLE.
  8. I added the missing semicolon after oauth_callback="oob".

享受吧!

这是您的代码的固定版本:

Here's a fixed version of your code:

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())

这篇关于使用 Python 3 从 Twitter API 检索请求令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆