04 August 2012

先说下,自己在web开发这里是完全的新手,很多基础的概念也刚刚接触,导致在做oauth认证登陆以及调用api的功能的时候,比较痛苦。但好歹,现在效果上来说,还是实现了。很可能本文写的东西走了弯路,或者在高手眼里根本就是错的,请评论指正,谢谢。

在做四家的oauth的时候,人人,微博,腾讯以及豆瓣的时候,发现其他几家还文档相对清晰,同时由于是实现的oauth2.0,因此实现起来简单;但豆瓣,首先用的是1.0的标准,同时,被人吐槽了超级多的文档,也让我在做的时候非常的不给力。还真是挺奇怪的,为什么豆瓣这样一家这么先锋的互联网企业,在oauth认证的时候还守着1.0标准。不过后期实现下来,发现也不能完全怪豆瓣文档不清晰,他们应该在文档里加一句话,请参考标准oauth1.0协议。

这个link可以验证你计算签名是否计算正确。

下文的代码就以发一条豆瓣说为例子,希望能帮助到大家。完全的oauth认证实现,等项目完成会开源。

import requests
import json
import hashlib
import sys
import urllib
import time
import hmac
import chardet

#douban

def get_signature_base_string(method, url, timestamp, nonce): #计算签名
    http_method = method #HTTP方法
    base_url = url #API地址
    params = [
            ('oauth_consumer_key', ''), #douban-app-key
            ('oauth_signature_method', 'HMAC-SHA1'),
            ('oauth_version','1.0'),
            ('oauth_token',''), #oauth-token
            ('oauth_timestamp', timestamp),
            ('oauth_nonce',nonce),
            ]
    params.sort() #先要排序下
    url_params = urllib.quote(urllib.urlencode(params))  #编码
    base_string = "%s&%s&%s" % (http_method, urllib.quote(base_url, safe=''),\
                                url_params)
    two = ''#oauth-token-secret
    one = ''#douban-app-secret
    secret = one + '&' + two  #将两个secret联合起来签名
    hmac_sha1 = hmac.new(secret, base_string, hashlib.sha1)
    hmac_sha1_string = hmac_sha1.digest()
    signature = hmac_sha1_string.encode('base64').rstrip()
    return signature

url = 'http://api.douban.com/miniblog/saying'
method = 'POST'
timestamp = str(int(time.time()))
nonce = hashlib.md5(str(time.time())).hexdigest()

args = {'oauth_token' : '',#oauth_token
        'oauth_consumer_key' : '',\
                                                             #douban_app_key
        'oauth_signature_method' : 'HMAC-SHA1',
        'oauth_signature' : get_signature_base_string(method, url,\
                                                         timestamp, nonce),
        'oauth_timestamp' : timestamp,
        'oauth_version' : '1.0',
        'oauth_nonce' : nonce}
#构造的请求参数

ss = ''
for item in args.keys():
    ss = ss + (item+'="'+args[item]+'",')

ss = ss + 'OAuth realm=""'

test_entry = """
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns:ns0="http://www.w3.org/2005/Atom" xmlns:db="http://www.douban.com/xmlns/">
<content>发一条豆瓣说,测试,请忽略</content>
</entry>
"""
#所谓的构造一个entry

headers = {'Authorization' : ss,
           'Content-type' : 'application/atom+xml'}
#头部必须定义好
           

my_config = {'verbose': sys.stderr}
r = requests.post(url, data=test_entry, headers=headers, config=my_config)
print r.text


blog comments powered by Disqus