2010-01-26 146 views
4

目前我正在使用OAuth協議連接Twitter API並使用Python編寫代碼。作爲大多數用戶,我認爲規格中最難的部分是處理簽名。在Python中爲OAuth簽名請求

在圍繞網絡尋找解決方案之後,我決定去我的自定義代碼,以便更好地理解發生了什麼。

對於其他用戶着想,我在這裏張貼一個非常簡單的和短期實現SHA1簽名規格的Python中:

import hmac 

from hashlib import sha1 
from urllib import quote, urlencode 
from base64 import b64encode 
from urlparse import urlparse 

def sign_request_sha1(url,method,data,secret=""): 
    pu = urlparse(urlparse(url).geturl()) 

    normUrl = "%s://%s%s%s" % (
     pu.scheme, 
     pu.hostname, 
     "" if not pu.port or {"http":80,"https":443}[pu.scheme] == pu.port else ":%d" % pu.port, 
     pu.path, 
          ) 

    names = data.keys() 
    names.sort() 

    sig = "%s&%s&%s" % (
      method.upper(), 
      quote(normUrl,''), 
      quote("&".join(["%s=%s" % (k,quote(data[k].encode('utf-8'),'')) for k in names]),''), 
        ) 

    key = "%s&%s" % (quote(CONSUMER_SECRET.encode('utf-8'),''),secret) 

    return b64encode(hmac.new(key,sig,sha1).digest()) 

的輸入參數的功能是:

  • 網址:您要爲特定的OAuth請求調用的網址。
  • 方法:根據您要發出請求的方式,這必須是「GET」或「POST」。
  • data:包含所有請求參數的字典,包括任何自定義參數,但不包括「oauth_signature」(出於顯而易見的原因)。
  • 祕密:您在協議初始階段收到的祕密令牌。

我用Twitter測試了它,它似乎能工作,但我想收到一些關於錯誤,改進等的評論。

最後,在這裏你找到一段代碼呼籲最初的「請求令牌」階段的代碼:

from random import getrandbits 
from base64 import b64encode 
from time import time 

def twitter_request_token(req,callback,errback): 
    req_url="http://twitter.com:80/oauth/request_token" 

    data = { \ 
    "oauth_consumer_key" : CONSUMER_KEY, 
    "oauth_nonce" : b64encode("%0x" % getrandbits(256))[:32], 
    "oauth_timestamp" : str(int(time())), 
    "oauth_signature_method" : "HMAC-SHA1", 
    "oauth_version" : "1.0", 
    "oauth_callback" : "http://localhost:8080/", 
     } 

    data["oauth_signature"] = sign_request_sha1(req_url,"GET",data) 

謝謝。

+0

你能解釋一下'normURL'練習的重點嗎? – SilentGhost 2010-01-26 10:14:13

+0

規格對於用於創建簽名的URL必須是非常嚴格的。 因此,從傳遞的URL開始,可能不符合規範(例如,由於某些字符爲大寫),該函數會生成一個新的URL。 第一行利用urlparse模塊獲得URL的第一次清理:這裏我不確定是否唯一的影響是使所有字符小寫。 在字符串插值中,它使用URL元素來形成新的URL,當它是所使用的方案的缺省值(80代表http和443代表https)時,省略端口。 – 2010-01-26 13:29:56

+0

所以你寫這個代替oauth.googlecode.com的代碼? – keturn 2010-01-27 01:19:02

回答

3

我對此的下意識反應是If You're Typing The Letters A-E-S Into Your Code, You're Doing It Wrong。或者,作爲redditor khafra recently reminded us of the Sicilian's version

哈哈..你這個傻瓜!你是受到經典失誤之一的受害者。最着名的是:絕不參與亞洲的陸地戰爭。但只有稍微不太出名的是:當有一個經過良好測試的庫會更好地完成時,千萬不要嘗試推出自己的加密程序!

我的意思是,我明白了。我第一次看到它,oauth.py也沒有給我留下深刻的印象。因爲它有很多工作,而且看起來更好,但似乎還沒有測試,所以我不知道。無論如何,測試或者沒有測試,它已經被更多的人審查和使用,而不是你的代碼。

但是,這只是我對密碼代碼重用主題的緊張,並沒有真正幫助你找出協議機制。它對我來說看起來沒什麼問題,但最近我還沒有在OAuth規範中找到我的頭。

只需使用一些更多的線,即pu.port業務;具有條件if表達式,or表達式和{}[]構造全部在一行中是真的難以閱讀。

如果你真的想要熟悉協議的人閱讀代碼,你最好問問the mailing list。如果您可以爲他們提供一個替代API,這會使其存儲庫中的代碼更加吸引新用戶,這對每個人都有好處。

+0

謝謝你的回答。這裏有幾點: - 一般來說,我同意你不寫你自己的加密庫:太多的警告,太多的細節,以使其正確。在我的情況下,我們不是在談論OpenSSL,只是使用加密函數(即MAC)的一小部分協議,並且它相當短。 - 絕不會將我的代碼作爲OAuth lib的替代品。也許,如果它有更多的記錄,它會更容易使用和更廣泛的傳播。 - 關於一行:我認爲{} []比具有相同的代碼作爲如果在兩行或多行中拆分更可讀。 – 2010-01-29 12:38:04