2

Python3を使用してTwitterAPIとインターフェイスし、アクセストークンのリクエストに使用するPIN番号を提供するページへのリンクを返そうとしています。ここで詳しく説明されているように:https ://dev.twitter.com/docs/auth/pin-based-authorization

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

最後に、このための開発を支援するPythonOAuthおよびTwitterモジュールの存在を認識していることに注意してください。ただし、学習体験として、使用しないことを選択しています。

お手数をおかけしますが、よろしくお願いいたします。

4

2 に答える 2

10

私が変更したものの概要:

  1. 私は交換しbinascii.b2a_base64ましたbase64.standard_b64encode
  2. bytes.decode('ascii')メソッドを使用してバイトを文字列に変換しました。str()は文字列にbを追加しているようです。
  3. パラメータの順序を次のように修正しましたhmac.new-KEY, MESSAGEではなく、MESSAGE, KEY
  4. の参照を削除しinclude_entitiesましたPARAMETER_STRING-リクエストでinclude_entitiesを使用しない場合(トークンリクエストには意味がないと思います)、PARAMETER_STRINGに含めることはできません
  5. -の先頭に追加oauth_callback=oobしましPARAMETER_STRINGた-oauth_signatureを除くすべてのoauthパラメーターをベース文字列に含める必要があります。
  6. リクエストが行われるセクションを変更して、Requestオブジェクトを事前に作成してから、Authorizationヘッダーを追加しました。HTTP本文としてAuthorizationヘッダーを送信していました。
  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())
于 2012-04-15T16:30:38.660 に答える
0

署名のベース文字列が正しいようには見えません。基本的に、私が見る限り、ベース文字列にパラメータを含めていません。

署名ベース文字列のトピックに関するTwitterドキュメントを引用するには:

  1. HTTPメソッドを大文字に変換し、出力文字列をこの値に設定します。
  2. '&'文字を出力文字列に追加します。
  3. URLをパーセントエンコードし、出力文字列に追加します。
  4. '&'文字を出力文字列に追加します。
  5. パラメータ文字列をパーセントエンコードし、出力文字列に追加します。

パラメータ文字列は次のように作成されます:(そして私は引用しています):

  1. 署名されるすべてのキーと値をパーセントエンコードします。
  2. パラメータのリストをエンコードされたキーのアルファベット順に並べ替えます。
  3. キーと値のペアごとに:
  4. エンコードされたキーを出力文字列に追加します。
  5. '='文字を出力文字列に追加します。
  6. エンコードされた値を出力文字列に追加します。
  7. キーと値のペアがさらに残っている場合は、出力文字列に「&」文字を追加します。
于 2012-04-11T11:30:33.357 に答える