2010-01-26 140 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