新浪sina微博用OAUTH给第三方鉴权
这里是一个python的例子。
新浪的比较原始,因为没用https,都用http,所以加入了签名过程。但是sina这整个过程正是纯正oauth的过程,其它qq,开心网,土豆等的oauth鉴权跟它大同小异。
开始前看以下签名oauth_signature的生成:
所有的OAuth请求使用同样的算法来生成(signature base string)签名字符基串和签名。base string是把http方法名,请求URL以及请求参数用&字符连起来后做URL Encode编码。具体来讲,base string由http方法名,之后是&,接着是过url编码(url-encoded)之后的url和访问路径及&。接下来,把所有的请求参数包括POST方法体中的参数,经过排序(按参数名进行文本排序,如果参数名有重复则再安参数值进行重复项目排序),使用%3D替代=号,并且使用%26作为每个参数之间的分隔符,拼接成一个字符串。这个算法可以简单表示为:
httpMethod + “&” +url_encode( base_uri ) + “&” +
sorted_query_params.each { | k, v |url_encode ( k ) + “%3D” +url_encode ( v )}.join(“%26”)
无论生成何种OAuth1.0请求,生成BASE STRING的规则始终不变。新浪微博要求所有的OAuth请求都使用HMAC-SHA1算法生成签名。
第一步获取request token
http://api.t.sina.com.cn/oauth/request_token?’+ \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + oauth_version
得到oauth_signature签名值的过程:
signature_base = ‘GET&http://api.t.sina.com.cn/oauth/request_token&’
signature_base = signature_base.replace(‘:’,’%3A’)
signature_base = signature_base.replace(‘/’,’%2F’)
oauth_consumer_key = ‘oauth_consumer_key=849827221’
oauth_nonce = ‘&oauth_nonce=08e59bdb879d2f4b96eb20158d7a5b47’
oauth_signature = ”
oauth_signature_method = ‘&oauth_signature_method=HMAC-SHA1’
oauth_timestamp = ‘&oauth_timestamp=’+str(long(time.time()))
oauth_version = ‘&oauth_version=1.0’
signature_sort_pars = oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_version
signature_sort_pars = signature_sort_pars.replace(‘&’,’%26′)
signature_sort_pars = signature_sort_pars.replace(‘=’,’%3D’)
signature_str = signature_base + signature_sort_pars
app_secret = ‘cbd4e8efb9872ac6543029ffff600dc7’ + ‘&’;
crypt.put_HashAlgorithm(“sha-1”)
crypt.put_EncodingMode(“Base64”)
crypt.put_Charset(“utf-8”)
crypt.SetHmacKeyString(app_secret)
signature = crypt.hmacStringENC(signature_str.encode(‘utf-8′))
oauth_signature =’&oauth_signature=’ + signature;
第二步用IE打开以下URL交给用户输入用户名、密码来获得授权
http://api.t.sina.com.cn/oauth/authorize?oauth_token=’+oauth_token+’&oauth_callback=http://www.hanborq.com/static/test_ms_live_oauth.html’
第三步用以下URL获得access token
http://api.t.sina.com.cn/oauth/access_token?’ + \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + \
oauth_token_str + oauth_verifier_str + oauth_version
第四步用以下URL获取用户信息
http://api.t.sina.com.cn/users/show/’+user_id+’.xml?’ + \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + \
oauth_token_str + oauth_version
源文件如下(test_oauth.py):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys, string, socket
import time
import urllib2
import urllib
import htmllib
import formatter
import cStringIO
import traceback
import datetime
import codecs
import win32com.client
import hashlib
# 需要到 http://www.chilkatsoft.com/python.asp 这里下载这个库,把其中的_chilkat.pyd和chilkat.py放到python的site-packages目录,
# 是个商业模块,只有30天trial。
import chilkat
status = ‘start’
class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
def http_error_301(self, req, fp, code, msg, headers): #永久重定向
print ‘========== ‘+u'(301)永久重定向:’+’ ==========’
print str(‘req=====> ‘ +req)
print str(‘fp======> ‘ + fp)
print str(‘code====> ‘ + code)
print str(‘msg=====> ‘+ msg)
print str(‘headers=> ‘+ headers)
print ‘========== END ==========’
result = urllib2.HTTPRedirectHandler.http_error_301(self, req, fp, code, msg, headers)
return result
def http_error_302(self, req, fp, code, msg, headers): #临时重定向
print ‘========== ‘+u'(302)临时重定向:’+’ ==========’
print str(‘req=====> ‘ +req)
print str(‘fp======> ‘ + fp)
print str(‘code====> ‘ + code)
print str(‘msg=====> ‘+ msg)
print str(‘headers=> ‘+ headers)
print ‘========== END ==========’
global status
if status == ‘start’:
status = ‘get_verify_code’
result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
else:
result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
return result
def DoWork():
try:
# 获取request token
crypt = chilkat.CkCrypt2()
success = crypt.UnlockComponent(“Anything for 30-day trial.”)
if (success != True):
print crypt.lastErrorText()
signature_base = ‘GET&http://api.t.sina.com.cn/oauth/request_token&’
signature_base = signature_base.replace(‘:’,’%3A’)
signature_base = signature_base.replace(‘/’,’%2F’)
”’
oauth_callback = ‘oauth_callback=http://www.hanborq.com/static/test_ms_live_oauth.html’
oauth_callback = oauth_callback.replace(‘:’,’%3A’)
oauth_callback = oauth_callback.replace(‘/’,’%2F’)
oauth_callback_header = oauth_callback
oauth_callback = oauth_callback.replace(‘%’,’%25′) ”’
oauth_consumer_key = ‘oauth_consumer_key=849827221’
oauth_nonce = ‘&oauth_nonce=08e59bdb879d2f4b96eb20158d7a5b47’
oauth_signature = ”
oauth_signature_method = ‘&oauth_signature_method=HMAC-SHA1’
oauth_timestamp = ‘&oauth_timestamp=’+str(long(time.time()))
oauth_version = ‘&oauth_version=1.0’
signature_sort_pars = oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_version
signature_sort_pars = signature_sort_pars.replace(‘&’,’%26′)
signature_sort_pars = signature_sort_pars.replace(‘=’,’%3D’)
signature_str = signature_base + signature_sort_pars
app_secret = ‘cbd4e8efb9872ac6543029ffff600dc7’ + ‘&’;
#signature_str = ‘GET&http%3A%2F%2Fapi.t.sina.com.cn%2Foauth%2Frequest_token&oauth_consumer_key%3D888888888%26oauth_nonce%3D08e59bdb879d2f4b96eb20158d7a5b47%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1288149739%26oauth_version%3D1.0a’
#app_secret = ‘e547036cd665c647f4561ede6820fde0&’
crypt.put_HashAlgorithm(“sha-1”)
crypt.put_EncodingMode(“Base64”)
crypt.put_Charset(“utf-8″)
crypt.SetHmacKeyString(app_secret)
#crypt.SetHmacKeyEncoded(app_secret,”Base64″)
signature = crypt.hmacStringENC(signature_str.encode(‘utf-8′))
print crypt.lastErrorText()
crypt = None
oauth_signature =’&oauth_signature=’ + signature;
print ‘SIGNATURE: string=> ‘ + signature_str
print ‘SIGNATURE: result=> ‘ + oauth_signature
sech = None
#urllib.urlencode({‘consumer_secret’:’cbd4e8efb9872ac6543029ffff600dc7′, ‘oauth_callback’:’http://www.hanborq.com/static/test_ms_live_oauth.html’,
#’oauth_consumer_key’:’849827221′, ‘oauth_nonce’:’QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk’, ‘oauth_signature_method’:’HMAC-SHA1′,
#’oauth_timestamp’:’1272323042′, ‘oauth_version’:’1.0′})
url = ‘http://api.t.sina.com.cn/oauth/request_token?’+ \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + oauth_version
print ‘REQUEST URL=> ‘ + url
req = urllib2.Request(url)
opener = urllib2.build_opener(SmartRedirectHandler())
fd = opener.open(req, sech) #urllib2.urlopen(req,sech)
url = fd.url
webContent = fd.read()
print ‘URL===> ‘ + url
print ‘========== ‘+u’内容:’+’ ==========’
print webContent
print ‘========== END ==========’
if url == ”:
print ‘ERROR: fd.url is Null’
return
pars = webContent.split(‘&’)
oauth_token = ”
oauth_token_secret = ”
for par in pars:
name = par.partition(‘=’)[0]
value = par.partition(‘=’)[2]
if name == ‘oauth_token’:
oauth_token = value
elif name == ‘oauth_token_secret’:
oauth_token_secret = value;
else:
print ‘URL PARAMETERS: NAME: ‘ + name + ‘, VALUE: ‘ + value
print ‘oauth_token========> ‘ + oauth_token
print ‘oauth_token_secret=> ‘ + oauth_token_secret
if oauth_token == ”:
print ‘ERROR: oauth_token is Null’
return
if oauth_token_secret == ”:
print ‘ERROR: oauth_token_secret is Null’
return
time.sleep(1)
# 用户认证
req = ‘http://api.t.sina.com.cn/oauth/authorize?oauth_token=’+oauth_token+’&oauth_callback=http://www.hanborq.com/static/test_ms_live_oauth.html’
ie=win32com.client.Dispatch(“InternetExplorer.Application”)
ie.Navigate(req)
ie.Visible=1
ie.Toolbar = 0
ie.StatusBar=0
ie.AddressBar=0
ie.menubar=0
ie.FullScreen=0
ie.Resizable=1
#ie.left=-5;
#ie.top=-25;
ie.Height=480;
ie.Width=640;
while ie.Busy:
time.sleep(1)
# 等待窗口大小改变(需要等待鉴权完成,r然后手工改变),来检测是否完成鉴权。
while ie.Width == 640:
time.sleep(1)
print ‘URL===> ‘+ie.LocationURL
print ‘========== ‘+u’内容:’+’ ==========’
print ie.Document
print ‘========== END ==========’
urlContent = ie.LocationURL
urlContent = urlContent.partition(‘?’)[2]
if urlContent == ”:
print ‘ERROR: ie.LocationURL is Null’
ie.Stop()
ie.Quit()
ie = ”
return
pars = urlContent.split(‘&’)
oauth_token = ”
oauth_verifier = ”
for par in pars:
name = par.partition(‘=’)[0]
value = par.partition(‘=’)[2]
if name == ‘oauth_token’:
oauth_token = value
elif name == ‘oauth_verifier’:
oauth_verifier = value;
else:
print ‘URL PARAMETERS: NAME: ‘ + name + ‘, VALUE: ‘ + value
print ‘oauth_token=====> ‘ + oauth_token
print ‘oauth_verifier==> ‘ + oauth_verifier
if oauth_token == ”:
print ‘ERROR: oauth_token is Null’
ie.Stop()
ie.Quit()
ie = ”
return
if oauth_verifier == ”:
print ‘ERROR: oauth_verifier is Null’
ie.Stop()
ie.Quit()
ie = ”
return
ie.Stop()
ie.Quit()
ie = ”
time.sleep(1)
# 获取access token
crypt = chilkat.CkCrypt2()
success = crypt.UnlockComponent(“Anything for 30-day trial.”)
if (success != True):
print crypt.lastErrorText()
signature_base = ‘GET&http://api.t.sina.com.cn/oauth/access_token&’
signature_base = signature_base.replace(‘:’,’%3A’)
signature_base = signature_base.replace(‘/’,’%2F’)
oauth_consumer_key = ‘oauth_consumer_key=849827221’
oauth_nonce = ‘&oauth_nonce=08e59bdb879d2f4b96eb20158d7a5b47’
oauth_signature = ”
oauth_signature_method = ‘&oauth_signature_method=HMAC-SHA1’
oauth_timestamp = ‘&oauth_timestamp=’+str(long(time.time()))
oauth_token_str = ‘&oauth_token=’+oauth_token
#oauth_token_secret_str = ‘&oauth_token_secret=’+oauth_token_secret
oauth_verifier_str = ‘&oauth_verifier=’+oauth_verifier
oauth_version = ‘&oauth_version=1.0’
signature_sort_pars = oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_token_str + oauth_verifier_str + oauth_version
signature_sort_pars = signature_sort_pars.replace(‘&’,’%26′)
signature_sort_pars = signature_sort_pars.replace(‘=’,’%3D’)
signature_str = signature_base + signature_sort_pars
secret = ‘cbd4e8efb9872ac6543029ffff600dc7’ + ‘&’ + oauth_token_secret;
crypt.put_HashAlgorithm(“sha-1”)
crypt.put_EncodingMode(“Base64”)
crypt.put_Charset(“utf-8″)
crypt.SetHmacKeyString(secret)
signature = crypt.hmacStringENC(signature_str.encode(‘utf-8′))
print crypt.lastErrorText()
crypt = None
oauth_signature =’&oauth_signature=’ + signature;
print ‘SIGNATURE: string=> ‘ + signature_str
print ‘SIGNATURE: result=> ‘ + oauth_signature
sech = None
#urllib.urlencode({‘oauth_consumer_key’:’849827221′, ‘oauth_nonce’:’08e59bdb879d2f4b96eb20158d7a5b47′,
#’oauth_signature’:signature, ‘oauth_signature_method’:’HMAC-SHA1′, ‘oauth_token’:oauth_token, ‘oauth_token_secret’:oauth_token_secret,
#’oauth_timestamp’:’1288149739′, ‘oauth_verifier’:oauth_verifier, ‘oauth_version’:’1.0′})
url = ‘http://api.t.sina.com.cn/oauth/access_token?’ + \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + \
oauth_token_str + oauth_verifier_str + oauth_version
print ‘REQUEST URL=> ‘ + url
req = urllib2.Request(url)
opener = urllib2.build_opener(SmartRedirectHandler())
fd = opener.open(req, sech) #urllib2.urlopen(req,sech)
url = fd.url
webContent = fd.read()
print ‘URL===> ‘ + url
print ‘========== ‘+u’内容:’+’ ==========’
print webContent
print ‘========== END ==========’
if url == ”:
print ‘ERROR: fd.url is Null’
return
pars = webContent.split(‘&’)
oauth_token = ”
oauth_token_secret = ”
user_id = ”
for par in pars:
name = par.partition(‘=’)[0]
value = par.partition(‘=’)[2]
if name == ‘oauth_token’:
oauth_token = value
elif name == ‘oauth_token_secret’:
oauth_token_secret = value;
elif name == ‘user_id’:
user_id = value;
else:
print ‘URL PARAMETERS: NAME: ‘ + name + ‘, VALUE: ‘ + value
print ‘oauth_token (access_token)========> ‘ + oauth_token
print ‘oauth_token_secret(access_token_secret)=> ‘ + oauth_token_secret
print ‘user_id=================================> ‘ + user_id
if oauth_token == ”:
print ‘ERROR: oauth_token(access_token) is Null’
return
if oauth_token_secret == ”:
print ‘ERROR: oauth_token_secret(access_token_secret) is Null’
return
if user_id == ”:
print ‘ERROR: user_id is Null’
return
time.sleep(1)
# 获取用户信息
crypt = chilkat.CkCrypt2()
success = crypt.UnlockComponent(“Anything for 30-day trial.”)
if (success != True):
print crypt.lastErrorText()
signature_base = ‘GET&http://api.t.sina.com.cn/users/show/’+user_id+’.xml&’
signature_base = signature_base.replace(‘:’,’%3A’)
signature_base = signature_base.replace(‘/’,’%2F’)
oauth_consumer_key = ‘oauth_consumer_key=849827221’
oauth_nonce = ‘&oauth_nonce=08e59bdb879d2f4b96eb20158d7a5b47’
oauth_signature = ”
oauth_signature_method = ‘&oauth_signature_method=HMAC-SHA1’
oauth_timestamp = ‘&oauth_timestamp=’+str(long(time.time()))
oauth_token_str = ‘&oauth_token=’+oauth_token
oauth_version = ‘&oauth_version=1.0’
signature_sort_pars = oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_token_str + oauth_version
signature_sort_pars = signature_sort_pars.replace(‘&’,’%26′)
signature_sort_pars = signature_sort_pars.replace(‘=’,’%3D’)
signature_str = signature_base + signature_sort_pars
secret = ‘cbd4e8efb9872ac6543029ffff600dc7’ + ‘&’ + oauth_token_secret;
crypt.put_HashAlgorithm(“sha-1”)
crypt.put_EncodingMode(“Base64”)
crypt.put_Charset(“utf-8″)
crypt.SetHmacKeyString(secret)
signature = crypt.hmacStringENC(signature_str.encode(‘utf-8′))
print crypt.lastErrorText()
crypt = None
oauth_signature =’&oauth_signature=’ + signature;
print ‘SIGNATURE: string=> ‘ + signature_str
print ‘SIGNATURE: result=> ‘ + oauth_signature
sech = None
#urllib.urlencode({‘oauth_consumer_key’:’849827221′, ‘oauth_nonce’:’08e59bdb879d2f4b96eb20158d7a5b47′,
#’oauth_signature’:signature, ‘oauth_signature_method’:’HMAC-SHA1′, ‘oauth_token’:oauth_token, ‘oauth_token_secret’:oauth_token_secret,
#’oauth_timestamp’:’1288149739′, ‘oauth_verifier’:oauth_verifier, ‘oauth_version’:’1.0′})
url = ‘http://api.t.sina.com.cn/users/show/’+user_id+’.xml?’ + \
oauth_consumer_key + oauth_nonce + oauth_signature + oauth_signature_method + oauth_timestamp + \
oauth_token_str + oauth_version
print ‘REQUEST URL=> ‘ + url
req = urllib2.Request(url)
req.add_header(‘Content-Type’,’application/json’)
req.add_header(‘Accept’,’application/json’)
opener = urllib2.build_opener(SmartRedirectHandler())
fd = opener.open(req, sech) #urllib2.urlopen(req,sech)
url = fd.url
webContent = fd.read()
print ‘URL===> ‘ + url
print ‘========== ‘+u’内容:’+’ ==========’
print webContent.decode(‘utf-8’)
print ‘========== END ==========’
if url == ”:
print ‘ERROR: fd.url is Null’
return
id = webContent.partition(‘<id>’)[2]
id = id.partition(‘</id>’)[0]
screen_name = webContent.partition(‘<screen_name>’)[2]
screen_name = screen_name.partition(‘</screen_name>’)[0]
name = webContent.partition(‘<name>’)[2]
name = screen_name.partition(‘</name>’)[0]
print ‘USER ID =======> ‘ + id.decode(‘utf-8’)
print ‘SCREEN NAME ===> ‘ + screen_name.decode(‘utf-8’)
print ‘NAME ==========> ‘ + name.decode(‘utf-8’)
print ‘CHEERS, Result is OK!’
except urllib2.URLError, e:
print traceback.format_exc()
print str(e)
return
except Exception,e:
print traceback.format_exc()
print str(e)
return
if __name__ == ‘__main__’ :
DoWork()