天天看點

新浪微網誌開發(上)

最近幾天一直在學習新浪微網誌的授權驗證,在論壇上下了個例子,也找到了相關的部落格文章。。以為很簡單能搞懂,但是費了很長時間,還是一頭霧水。。後來想想,其實别人提供的隻是一些接口、方法,而我對授權的過程并沒有認真的學習過,是以對于代碼中那些奇怪的方法倍感陌生。。現在把自己的一些心得補充進來。

對于界面及資料庫使用就不在啰嗦,隻诠釋下授權驗證部分。 

   新浪微網誌授權支援Oauth1.0 和Oauth2.0 ,後者對前者在過程中有所改變,詳細資訊可參考:

授權機制:

OAuth

新浪微網誌開放平台已推出OAuth2.0,同時提供對Web,桌面和移動應用程式的支援,并較1.0相比整個授權驗證流程更簡單更安全。也是未來最主要的使用者身份驗證和授權方式。

HTTP普通鑒權(Basic Authentication)方式

目前Basic Authentication僅用于開發者調試API接口。

不過這種方式不具有通用性,原部落格中采用Oauth1.0 方式,同時使用Signpost(開源項目)實作Oauth簽名。

SignPost 

Signpost 是一個簡單而且直覺的使用 OAuth 1.0 規範對 HTTP 消息進行簽名的 Java 解決方案。

參考上面内容,我們詳細的學習下如何使用signpost進行Oauth認證的。

了解授權過程

以新浪微網誌為例,為了使用新浪微網誌開放平台提供的API(應用程式接口),你需要先注冊一個應用,獲得一個專屬的App Key和App Secret。Key跟Secret的使用方式跟其他一些協定中的公鑰私鑰的方案相類似,你可以使用你所熟悉的程式設計語言将key和secret結合,為你發出的每個請求添加簽名,以此來向新浪微網誌開放平台表明自己身份的合法性。

OAuth請求循環可以分為如下四步:

新浪微網誌開發(上)

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 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 + "&" + rl_encode( base_uri ) "& + sorted_query_params.each { | k, v

簽名:由簽名字元基串按一定算法計算出來。(如HMAC-SHA1)

新浪微網誌要求所有的OAuth請求都使用HMAC-SHA1算法生成簽名。

傳回值oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8Z

擷取request tokenrequest 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=

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。

<a></a>

使用者認證

這一步主要是發送你擷取的oauth_token,并且獲得使用者的授權。一般來說,WEB應用會簡單的重定向到相應的頁面,桌面應用程式會給出URL并要求使用者自行驗證.

<a href="http://api.t.sina.com.cn/oauth/authorize?oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc">http://api.t.sina.com.cn/oauth/authorize?oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc</a>

如使用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, 頁面直接傳回參數 c248561721393a78260b8d00ece7d703234256

如果使用者沒有登入新浪微網誌,則會要求使用者登入。否則将會出現一個頁面,使用者可以在此頁面上一鍵同意或者拒絕對此應用授權。使用者授權後,web應用頁面将會重定向至你指定的oauth_callback,如果是桌面應用,将會顯示PIN碼,使用者需要将PIN碼輸入你的應用中來完成授權過程。

如果使用了callback,那麼oauth_callback應該已經接到傳回的資訊,其中包含oauth_token和oauth_verifier。樣例如下:

oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&amp;oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY

這一步,我們需要擷取oauth_token ,oauth_verifier。

擷取access token(授權過的Oauth_token)

以下是請求參數清單:

oauth_consumer_key - GDdmIQH6jhtmLUypg82g 建立應用時生成的APP KEY。

oauth_nonce - 9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8 單次值,一個随機字元串 oauth_signature_method - HMAC-SHA1 簽名方法

oauth_token - 8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc 經過使用者授權的Request Token。

oauth_timestamp - 1272323047 時間戳

oauth_version - 1.0  Oauth版本号

oauth_token_secret - x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA

參數說明:

oauth_token:經過使用者授權的Request Token。

oauth_nonce:單次值,一個随機字元串,防止重複攻擊。該參數隻支援ASCII碼的字元串.

第一步,準備base string(使用上文提到的方法)

POST&amp;https://api.t.sina.com.cn/oauth/access_token&amp;oauth_consumer_key=GDdmIQH6jhtmLUypg82g&amp;oauth_nonce=9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8&amp;oauth_signature_method=HMAC-SHA1&amp;oauth_timestamp=1272323047&amp;oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&amp;oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY&amp;oauth_version=1.0

接着将consumer_secret和oauth_token_secret連接配接起來,中間用&amp;分割(這是準備密鑰的方法,下面還會用到):

MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&amp;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&amp;oauth_token_secret=J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA&amp;

user_id=819797&amp;

screen_name=openapi

現在就可以使用access token來釋出資訊了。

擷取使用者資訊

按使用者ID或昵稱傳回使用者資料以及使用者的最新釋出的一條微網誌消息。

請求參數:

必選

類型及範圍

說明

source

true

string

申請應用時配置設定的AppKey,調用接口時候代表應用的唯一身份。(采用OAuth授權方式不需要此參數)

:id

false

int64/string

使用者ID(int64)或者昵稱(string)。該參數為一個REST風格參數。調用示例見注意事項

user_id

int64

使用者ID,主要是用來區分使用者ID跟微網誌昵稱。當微網誌昵稱為數字導緻和使用者ID産生歧義,特别是當微網誌昵稱和使用者ID一樣的時候,建議使用該參數

screen_name

微網誌昵稱,主要是用來區分使用者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&amp;http://api.t.sina.com.cn/account/verify_credentials&amp;oauth_consumer_key=GDdmIQH6jhtmLUypg82g&amp;oauth_nonce=9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8&amp;oauth_signature_method=HMAC-SHA1&amp;oauth_timestamp=1272325550&amp;oauth_token=819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw&amp;oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY&amp;oauth_version=1.0

然後将oauth_comsumer_secret和oauth_token_secret以&amp;作為分隔符拼起來。将拼接後的字元串作為簽名的KEY進行加密,生成簽名。

key如下:

MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&amp;J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA

生成的簽名如下:

ICuKVLKetCO4axEppJBqOofFg/A=

接下來就可以通過http發送請求,生成的http header如下:

OAuth oauth_nonce="oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y",

oauth_timestamp="1272325550",

oauth_consumer_key="GDdmIQH6jhtmLUypg82g",

oauth_token="819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw", oauth_signature="ICuKVLKetCO4axEppJBqOofFg/A=",

響應如下:

{ 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[',

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 }

繼續閱讀