Oauth認證-新浪微博開發(上)

最近幾天一直在學習新浪微博的受權驗證,在論壇上下了個例子,也找到了相關的博客文章。。覺得很簡單能搞懂,可是費了很長時間,仍是一頭霧水。。後來想一想,其實別人提供的只是一些接口、方法,而我對受權的過程並無認真的學習過,因此對於代碼中那些奇怪的方法倍感陌生。。如今把本身的一些心得補充進來。
原文博客: http://www.cnblogs.com/hll2008/archive/2011/01/03/1924952.html
對於界面及數據庫使用就不在囉嗦,只詮釋下受權驗證部分。
新浪微博受權支持Oauth1.0 和Oauth2.0 ,後者對前者在過程當中有所改變,詳細信息可參考:
Oauth1.0 http://open.weibo.com/wiki/Oauth
Oauth2.0 http://open.weibo.com/wiki/index.php?title=Oauth2&redirect=no

受權機制:
大部分REST API的訪問如發表微博,獲取私信都須要用戶身份。目前用戶身份鑑權有OAuth和Basic Auth(僅用於開發者調試接口)兩種方式。

OAuth

OAuth是一種國際通用的受權方式, OAuth的官方技術說明可參看 http://oauth.net/2/ (英文)。
新浪微博開放平臺已推出OAuth2.0,同時提供對Web,桌面和移動應用程序的支持,並較1.0相比整個受權驗證流程更簡單更安全。也是將來最主要的用戶身份驗證和受權方式。

HTTP普通鑑權(Basic Authentication)方式

Basic Authentication是一種經過HTTP頭傳遞用戶身份的受權方式。在非HTTPS方式下使用存在密碼被竊聽風險。採用普通鑑權(Basic Authentication)時app_key(consumer key)經過請求參數直接傳遞,參數名爲 source=consumer key,如
curl -u user:password -d "source=10001&status=api test" http://api.t.sina.com.cn/statuses/update.xml 
Basic Auth編程也能夠參看這篇文章 http://www.cnblogs.com/QLeelulu/archive/2009/11/22/1607898.html
當前Basic Authentication僅用於開發者調試API接口。
新浪開發平臺提供一套SDK(下載地址 http://open.weibo.com/wiki/SDK),你能夠調用其方法實現新浪微博的受權。
不過這種方式不具備通用性,原博客中採用Oauth1.0 方式,同時使用Signpost(開源項目)實現Oauth簽名。
SignPost
Signpost 是一個簡單並且直觀的使用 OAuth 1.0 規範對 HTTP 消息進行簽名的 Java 解決方案。
參考上面內容,咱們詳細的學習下如何使用signpost進行Oauth認證的。
瞭解受權過程
以新浪微博爲例,爲了使用新浪微博開放平臺提供的API(應用程序接口),你 須要先註冊一個應用,得到一個專屬的 App Key和App Secret。Key跟Secret的使用方式跟其餘一些協議中的公鑰私鑰的方案相相似,你可使用你所熟悉的編程語言將key和secret結合,爲你發出的每一個請求添加簽名,以此來向新浪微博開放平臺代表本身身份的合法性。
OAuth請求循環能夠分爲以下四步:
oauth_flowchart.jpg
OAuth提供兩種認證方式:query-string和http headers。咱們推薦使用http header進行認證。
請求籤名

oauth/request_token

經過訪問該接口獲取未受權的 Request Token訪問以get方式請求,幷包含如下參數:
  • oauth_consumer_key: 建立應用時生成的APP KEY。
  • oauth_signature_method: 簽名方法,建議使用「HMAC-SHA1」。
  • oauth_timestamp:時間戳。生成Base String時的時間戳。
  • oauth_nonce:單次值,一個隨機字符串,防止重複***。該字段只支持ASCII碼的字符。
  • oauth_version : OAuth協議版本。填寫「1.0」。
  • oauth_signature:簽名值,是由根據上面的5個參數生成的 Base String經HMAC-SHA1算法計算得出。
全部的OAuth請求 使用一樣的算法來生成(signature base string)簽名字符基串和簽名。base string是把http方法名,請求URL以及請求參數用&字符連起來後作URL Encode編碼。
簽名字符基串:把http方法名,請求URL以及請求參數用&字符連起來後作URL Encode編碼,不管生成何種OAuth1.0請求,生成BASE STRING的規則始終不變。
具體來說,base string由http方法名,以後是&,接着是過url編碼(url-encoded)以後的url和訪問路徑及&。接下來,把全部的請求參數包括POST方法體中的參數,通過排序(按參數名進行文本排序,若是參數名有重複則再安參數值進行重複項目排序),使用=替代=號,而且使用&做爲每一個參數之間的分隔符,拼接成一個字符串。這個算法能夠簡單表示爲:
httpMethod + "&" + url_encode( base_uri ) + "&" + sorted_query_params.each { | k, v | url_encode ( k ) + "=" + url_encode ( v ) }.join("&")

簽名:由簽名字符基串按必定算法計算出來。(如HMAC-SHA1)
新浪微博要求全部的OAuth請求都使用 HMAC-SHA1算法生成簽名。

返回值

oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8Z

獲取request token

request token是進行用戶認證的第一步。這一步主要有兩個目的:
第一,告訴新浪微博你將要作什麼
第二,告訴新浪微博你在callback裏要作什麼
下面舉個例子,如下是請求用的參數: (注意,這裏是請求用到的參數,並不必定是【請求參數】)
consumer secret - "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" 這個作什麼用 ?
oauth_callback - http://localhost:3005/the_dance/process_callback?service_provider_id=11 受權後的重定向的URL
oauth_consumer_key - GDdmIQH6jhtmLUypg82g 建立應用時生成的APP KEY。
oauth_nonce - QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk 單次值,一個隨機字符串,防止重複***
oauth_signature_method - HMAC-SHA1 簽名方法
oauth_timestamp - 1272323042 時間戳
oauth_version - OAuth協議版本

個人理解:請求時,使用consumer_secret做爲密鑰對請求參數進行加密,而傳輸過程當中只傳輸公鑰(consumer_key),因此在接口參數中只有oauth_consumer_key,而沒有包含上文提到的consumer_secret。
好比,文中提到的oauth_callback等參數做爲字符基串,生成oauth_signature:簽名值,再做爲請求參數傳輸。

第一步,用上文提到的算法造成BASE STRING。須要注意的是callback在URL中包含請求參數,因爲參數只CALLBACK URL的一部分,因此並不須要將其提出成爲獨立的參數。 URL必須按照單個字符串來考慮。生成的BASE STRING以下:
POST&https://api.t.sina.com.cn/oauth/request_token&oauth_callback=http://loca
因爲咱們還未獲取到oauth_token和oauth_token_secret,因此咱們的BASE STRING裏沒有包含oauth_token和oauth_token_secret。
接下來使用signing key(App Secret後加一個&符)從base string生成oauth_signature: ?
8wUi7m5HFQy76nowoCThusfgB+Q=
接下來就能夠向 http://api.t.sina.com.cn/oauth/request_token 發送請求。 生成的http header以下:
OAuth oauth_nonce="QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk", 
oauth_callback="http://localhost:3005
當服務器端接到請求以後,會返回包含oauth_token,oauth_token_secret等內容,另外oauth_callback_confirmed字段若是爲true就表示callback生效。服務器端的響應以下:
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA&oauth_callback_confirmed=true  
這時須要將oauth_token和oauth_token_secret記下,咱們須要用這個參數來獲取access token。

用戶認證

這一步主要是發送你獲取的oauth_token,而且得到用戶的受權。通常來講,WEB應用會簡單的重定向到相應的頁面,桌面應用程序會給出URL並要求用戶自行驗證.
新浪微博開放平臺的驗證URL是 http://api.t.sina.com.cn/oauth/authorize 。要求必須以oauth做爲參數,通常來講請求格式以下:
如使用XML/JSON返回方式(參看後文),需傳遞如下附加參數:
  • oauth_token 上一步獲(即:oauth/request_token接口調用)取到的oauth token
  • oauth_callback, 須要進行url encode
  • display,定義頁面調用類型,目前咱們提供了6種調用類型
    普通web調用:display=page 這個也是默認調用類型
    Android,iPhone調用:display=mobile
        wap訪問頁面自動調用:display=wap 咱們會根據信息頭來判斷是wap1.2仍是wap2.0
wap1.2頁面調用:display=wap1.2 供wap1.2訪問
wap2.0頁面調用:display=wap2.0 供wap2.0訪問
    popup彈窗調用:display=popup
json 或 xml(一般移動終端使用)
  • userId 新浪通行證帳戶名
  • passwd 密碼

使用說明

  • 當請求參數 oauth_callback=oob 則代表爲桌面應用,會提示用戶作桌面應用操做.
部分移動終端客戶端可能不方便訪問Web/WAP頁面,可使用如下方法
  • oauth_callback=json, 頁面直接返回參數
{"oauth_token":"c248561721393a78260b8d00ece7d703", "oauth_verifier":"234256"}
  • oauth_callback=xml, 頁面直接返回參數
<oauth_token>c248561721393a78260b8d00ece7d703</oauth_token> <oauth_verifier>234256</oauth_verifier>
若是用戶沒有登陸新浪微博,則會要求用戶登陸。不然將會出現一個頁面,用戶能夠在此頁面上一鍵贊成或者拒絕對此應用受權。用戶受權後,web應用頁面將會重定向至你指定的oauth_callback,若是是桌面應用,將會顯示PIN碼,用戶須要將PIN碼輸入你的應用中來完成受權過程。
若是使用了callback,那麼oauth_callback應該已經接到返回的信息,其中包含oauth_token和oauth_verifier。樣例以下:
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY

這一步,咱們須要獲取oauth_token ,oauth_verifier。

獲取access token(受權過的Oauth_token)

新浪微博開放平臺access token請求地址爲: http://api.t.sina.com.cn/oauth/access_token
如下是請求參數列表:
 oauth_consumer_key - GDdmIQH6jhtmLUypg82g 建立應用時生成的APP KEY。
oauth_nonce - 9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8 單次值,一個隨機字符串 oauth_signature_method - HMAC-SHA1 簽名方法
oauth_token - 8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc 通過用戶受權的Request Token。
oauth_timestamp - 1272323047 時間戳
oauth_verifier - pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY 可選。在oauth/authorize這一步中,新浪微博給出的認證碼。
oauth_version - 1.0 Oauth版本號
oauth_token_secret - x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA

參數說明:
  • oauth_consumer_key: 建立應用時生成的APP KEY。
  • oauth_token:通過用戶受權的Request Token。
  • oauth_signature_method: 簽名方法,建議使用「HMAC-SHA1」。
  • oauth_timestamp:時間戳。生成Base String時的時間戳。
  • oauth_nonce:單次值,一個隨機字符串,防止重複***。該參數只支持ASCII碼的字符串.
  • oauth_version : OAuth協議版本。填寫「1.0」。
  • oauth_verifier: 可選。在oauth/authorize這一步中,新浪微博給出的認證碼。
  • oauth_signature:簽名值,是由根據上面的幾個參數生成的 Base String經HMAC-SHA1算法計算得出。

第一步,準備base string(使用上文提到的方法)
POST&https://api.t.sina.com.cn/oauth/access_token&oauth_consumer_key=GDdmIQH6jhtmLUypg82g&oauth_nonce=9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323047&oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY&oauth_version=1.0
接着將consumer_secret和oauth_token_secret鏈接起來,中間用&分割(這是準備密鑰的方法,下面還會用到):
MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA
生成的OAuth簽名以下:
PUw/dHA4fnlJYM6RhXk5IU/0fCc=
而後向給定的url發送請求, 請求頭部必定要包含request token,request頭部以下:
OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", 
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1272323047",
oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw/dHA4fnlJYM6RhXk5IU/0fCc=",
oauth_version="1.0"
新浪微博開放平臺會返回應用須要的信息,包括 用戶名,oauth_token/oaut_token_secret(固然這裏就是access token了)。 response內容以下:
oauth_token=819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw&oauth_token_secret=J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA&
user_id=819797&
screen_name=openapi
如今就可使用access token來發布信息了。

獲取用戶信息

按用戶ID或暱稱返回用戶資料以及用戶的最新發布的一條微博消息。
請求參數:
必選 類型及範圍 說明
source true string 申請應用時分配的AppKey,調用接口時候表明應用的惟一身份。(採用OAuth受權方式不須要此參數)
:id false int64/string 用戶ID(int64)或者暱稱(string)。該參數爲一個REST風格參數。調用示例見注意事項
user_id false int64 用戶ID,主要是用來區分用戶ID跟微博暱稱。當微博暱稱爲數字致使和用戶ID產生歧義,特別是當微博暱稱和用戶ID同樣的時候,建議使用該參數
screen_name false string 微博暱稱,主要是用來區分用戶UID跟微博暱稱,當兩者同樣而產生歧義的時候,建議使用該參數
:id、user_id、screen_name這三個參數三者至少要提供一個

接下來,就能夠進行用戶驗證(若是驗證成功,將會返回用戶的詳細信息)了。如下是進行用戶驗證的相關參數:
oauth_consumer_key - GDdmIQH6jhtmLUypg82g
oauth_nonce - oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y
oauth_signature_method - HMAC-SHA1
oauth_token - 819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw
oauth_timestamp - 1272325550
oauth_version - 1.0
使用BASE STRING生成算法:
POST&http://api.t.sina.com.cn/account/verify_credentials&oauth_consumer_key=GDdmIQH6jhtmLUypg82g&oauth_nonce=9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272325550&oauth_token=819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw&oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY&oauth_version=1.0
而後將oauth_comsumer_secret和oauth_token_secret以&做爲分隔符拼起來。將拼接後的字符串做爲簽名的KEY進行加密,生成簽名。
key以下:
MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA
生成的簽名以下:
ICuKVLKetCO4axEppJBqOofFg/A=
接下來就能夠經過http發送請求,生成的http header以下:
OAuth oauth_nonce="oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y", 
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1272325550",
oauth_consumer_key="GDdmIQH6jhtmLUypg82g",
oauth_token="819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw", oauth_signature="ICuKVLKetCO4axEppJBqOofFg/A=",
oauth_version="1.0"
響應以下:
{ weibo=null, id=1803876591, name='loopa', screenName='loopa', location='北京 海淀區', description='2fBAcRG0]8OGRvp', profileImageUrl='http://tp4.sinaimg.cn/1803876591/50/0', url='', isProtected=false, followersCount=23, statusCreatedAt=Mon Sep 27 13:50:14 CST 2010, statusId=2847344825, statusText='uhYFQJ[', statusSource='<a href="" rel="nofollow">微博開放平臺接口</a>', statusTruncated=false, statusInReplyToStatusId=0, statusInReplyToUserId=0, statusFavorited=false, statusInReplyToScreenName='', profileBackgroundColor='', profileTextColor='', profileLinkColor='', profileSidebarFillColor='', profileSidebarBorderColor='', friendsCount=1, createdAt=Fri Aug 27 00:00:00 CST 2010, favouritesCount=0, utcOffset=-1, timeZone='', profileBackgroundImageUrl='', profileBackgroundTile='', following=false, notificationEnabled=false, statusesCount=8509, geoEnabled=false, verified=false }
相關文章
相關標籤/搜索