http://blog.csdn.net/arthurchenjs/article/details/6567563
由于工作需要,我最近接觸了現(xiàn)在開放平臺基本都會使用的OAuth協(xié)議。我相信OAuth是很強(qiáng)大的,但是,終于我還是切身的領(lǐng)教了中國互聯(lián)網(wǎng)的的強(qiáng)大之處。
我的目的是制作一個iphone平臺比較通用的OAuth庫封裝,通過簡單的配置URL和key等參數(shù),就可以快速的支持其開放平臺,包括界面也是由我來完成。原先以為都是有開源封庫的,只要簡單的在做一層wrapper,開放幾個接口應(yīng)該就可以了。可惜的是想法是美好的,現(xiàn)實(shí)是殘酷,道路也肯定是曲折的。
我看到的OAuth
說實(shí)話,我沒有比較好的研究過OAuth這個協(xié)議,大致上來說,OAuth協(xié)議的目的是讓第三方在不接觸到用戶的賬號和密碼情況下可以訪問第一方的資源。這想起來真是太強(qiáng)大了。
OAUTH認(rèn)證授權(quán)就三個步驟,三句話可以概括:
1. 獲取未授權(quán)的Request Token
2. 獲取用戶授權(quán)的Request Token
3. 用授權(quán)的Request Token換取Access Token
當(dāng)應(yīng)用拿到Access Token后,就可以有權(quán)訪問用戶授權(quán)的資源了。大家肯能看出來了,這三個步驟不就是對應(yīng)OAUTH的三個URL服務(wù)地址嘛。一點(diǎn)沒錯,上面的三個步驟中,每個步驟分別請求一個URL,并且收到相關(guān)信息,并且拿到上步的相關(guān)信息去請求接下來的URL直到拿到Access Token。
開源項(xiàng)目
很幸運(yùn),網(wǎng)絡(luò)上開源項(xiàng)目有Objective-C版本的,我好不客氣的checkout了,沒有很深入的研究內(nèi)部的代碼,不過看到代碼主要還是對數(shù)據(jù)結(jié)構(gòu)的封裝,對URLRequest的封裝,還有一些加密的處理。小做修改,就可以將其中桌面版的移植到手機(jī)版本的。不過我馬上發(fā)現(xiàn)新浪的代碼也是使用OAuthConsumer這份代碼。我毫不猶豫的投入到新浪的懷抱中。
新浪微博
l 新浪的判斷機(jī)制
新浪微博被認(rèn)為是行業(yè)翹楚,其代碼和api應(yīng)該不會差到哪。例子的程序跑的挺好,可是后來看到其中一段代碼和注釋,我真的凌亂了。
/*********************************************************************************************************
I am fully aware that this code is chock full 'o flunk. That said:
- first we check, using standard DOM-diving, for the pin, looking at both the old and new tags for it.
- if not found, we try a regex for it. This did not work for me (though it did work in test web pages).
- if STILL not found, we iterate the entire HTML and look for an all-numeric 'word', 7 characters in length
Ugly. I apologize for its inelegance. Bleah.
*********************************************************************************************************/
- (NSString *) locateAuthPinInWebView: (UIWebView *) webView {
NSString *pin;
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerText"];
NSLog(@"html:%@", [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"]);
if (html.length == 0) return nil;
const char *rawHTML = (const char *) [html UTF8String];
int length = strlen(rawHTML), chunkLength = 0;
for (int i = 0; i < length; i++) {
if (rawHTML[i] < '0' || rawHTML[i] > '9') {
if (chunkLength == 6) {
char *buffer = (char *) malloc(chunkLength + 1);
memmove(buffer, &rawHTML[i - chunkLength], chunkLength);
buffer[chunkLength] = 0;
pin = [NSString stringWithUTF8String: buffer];
free(buffer);
return pin;
}
chunkLength = 0;
} else
chunkLength++;
}
return nil;
}
這段代碼我也沒細(xì)品,但是基本可以看出是在網(wǎng)頁的html代碼中找到一串?dāng)?shù)字,找到了就認(rèn)為是授權(quán)pin碼,我的天啊,算了,人家也道歉了。可是我真不知道怎么來做這個協(xié)議了。
后來才發(fā)現(xiàn),其實(shí)只要取到verifier就可以了,這是直接在url里面就有,不用去html里面扣。
l 新浪支持的XAuth協(xié)議
什么是XAuth呢? 我沒有去考據(jù)究竟XAuth是誰的創(chuàng)造, 它幾乎搬了大部分OAuth的內(nèi)容, 不過解決了一個什么問題呢? 解決了一個 "OAuth認(rèn)證必須跳轉(zhuǎn)到第一方去輸入密碼" 的問題(美其名曰提升用戶體驗(yàn))。我真不知道說什么了, 第三方是可以得到用戶密碼的, 那它是不是直接把OAuth的第一大feature給咔嚓掉了——那basic auth不能滿足你么?
l OAuth提供兩種認(rèn)證方式
在新浪的文檔中,我還注意到了這一段話:OAuth提供兩種認(rèn)證方式:query-string和http headers。我們推薦使用http header進(jìn)行認(rèn)證。
也許是這段話,騰訊微博做出了選擇,讓我悲劇了好長一段時間,終于向企鵝大哥妥協(xié)了。
騰訊微博
很快,調(diào)通了新浪微博后,我就開始騰訊的歷程了。可是怎么都是不能授權(quán)成功,第一步獲取token就失敗了。后來我在FAQ中找到一段話:
請帶上所有OAuth需要的參數(shù),并按照規(guī)范傳輸(暫不支持Header方式傳參,請通過GET,POST方式),騰訊微博授權(quán)協(xié)議在OAuth 【RFC 5849】 標(biāo)準(zhǔn)基礎(chǔ)上開發(fā)。第一步需帶上回調(diào)URL(oauth_callback參數(shù)),不是在第二步(非同于基他微博OAuth授權(quán))。回調(diào)url需根據(jù)[RFC3986] 所定義的百分號機(jī)制進(jìn)行URL轉(zhuǎn)義。
我真的懷疑騰訊為了和新浪不兼容才不支持header方式傳參的。就因?yàn)檫@一條,我最后還是選擇了騰訊的封裝,而棄用了新浪的封裝。
另一個問題是:在請求request_token時傳遞oauth_callback參數(shù), 因?yàn)閷憸y試沒用到callback, 所以肯定庫會幫我填上oob(out-of-bound), 不過讓我很崩潰的是, 給我跳轉(zhuǎn)到了一個這樣一個地方:
https://open.t.qq.com/oauth_html/oob?oauth_token=xxxxx&oauth_verifier=xxxxxx
結(jié)果是NOT FOUND了。
然后我又看到了下一條說明:
桌面應(yīng)用,手機(jī)應(yīng)用,因?yàn)闆]有callback_url(oauth_callback參數(shù)),所以在第一步傳CALLBACK時請用oauth_callback=null代替,不然得不到 PIN碼。“null”串不區(qū)分大小寫。
還有騰訊的不同之處還有是攔截url中的oauth_verifier=xxxxxx的部分來繼續(xù)操作。相比新浪的,也是靠譜一點(diǎn),可是也就是因?yàn)檫@個,后面豆瓣和網(wǎng)易我都沒能都支持。
搜狐微博
搜狐微博的支持似乎比較弱,但是中規(guī)中規(guī)中矩的,除了界面比較丑陋,沒有針對手機(jī)適配,其他的很容易就走通了流程了。
網(wǎng)易微博
開始我嘗試了網(wǎng)易微博的授權(quán),沒能成功。
首先我發(fā)現(xiàn)的明顯的一個不按照標(biāo)準(zhǔn)的地方是authorization步驟, 它提供了兩個接口, 一個是/oauth/authorize, 一個是/oauth/authenticate, 首先我先申明這兩個單詞我一直搞不清, 不過在網(wǎng)易給OAuth的分工中, 它們的工程師是這么定義的: authorize不處理callback, 直接展示verifier的頁面; 另一個, authenticate則處理callback. (至于給第二個傳oob會怎么樣, 有沒有返回oauth_callback_confirmed, 我都沒有細(xì)看了)。
另外小提一下, 它在回調(diào)你的callback地址的時候, 傳的參數(shù)名是oauth_token, 不過相信我, 我覺得那是oauth_verifier。
后來仔細(xì)研究了網(wǎng)易的協(xié)議后,我才發(fā)現(xiàn),其實(shí)并不是每一個都需要verifier。那怎么來確定是否同意授權(quán),只要重定向了,就可以認(rèn)為用戶已經(jīng)授權(quán),直接去換取accesstoeken就可以了。因?yàn)檫@樣豆瓣的問題也同樣的解決了。
還有,網(wǎng)易需要把重定向url加到在請求授權(quán)url時一起加上,他才不管你在header里已經(jīng)傳了。
最后還需要加上client_type=mobile,真是麻煩。
還有,網(wǎng)易的demo代碼真是不知道說什么了。不過算了,畢竟人家也是貢獻(xiàn)出來的。整個網(wǎng)易的objective-C代碼就是把騰訊的demo改改,然后就拿出來了。不過出現(xiàn)了和我一樣的問題,但是可能不知道重定向url的問題,出現(xiàn)了手動輸入pin的界面,這是我做庫所不能接受的,所以沒有采納。
豆瓣
開始豆瓣我也沒有能夠成功,他總是不會重定向到我的URL,轉(zhuǎn)而跳轉(zhuǎn)到其授權(quán)的界面。這大概是我使用騰訊封裝導(dǎo)致的結(jié)果。可是我還真沒好好的確認(rèn)這個流程了。
后來才發(fā)現(xiàn),只要在請求網(wǎng)頁地址的時候,需要吧重定向地址加到url,這樣才會正確重定向,并且和網(wǎng)易一樣,沒有verifier,直接請求就可以成功了。
豆瓣沒有Objective-C的代碼,沒有參考,很久都沒有解決,最后是解決網(wǎng)易的時候也一起解決的。
人人網(wǎng)
人人網(wǎng)使用的OAuth2.0,2.0的協(xié)議我沒有好好的看過,因?yàn)楝F(xiàn)在只有人人支持2.0所以我偷懶的直接使用了人人的代碼,所以,結(jié)果是2.0現(xiàn)在只支持人人授權(quán)。
人人的代碼是直接沖facebooksdk改改就拿來用的,也是有時候看看也覺得真是的,一點(diǎn)都不專業(yè)。
一點(diǎn)感觸
已經(jīng)不記得是在什么地方看到一篇文章, 作者一上來第一句話就是 "從OAuth可以看出一個互聯(lián)網(wǎng)企業(yè)的技術(shù)力", 雖然稍微有些偏激, 但多多少少有值得認(rèn)同的地方。
OAuth的應(yīng)用越來越廣泛, 互聯(lián)網(wǎng)企業(yè)拿著互聯(lián)網(wǎng)開發(fā)的新年開發(fā)著自己的平臺, 這是一件很好的事情.從開發(fā)角度來說,不得不承認(rèn)OAuth并不簡單, 我也并不精通OAuth, 偷懶了用了別人的庫或多或少出現(xiàn)了些問題.。我依然比較郁悶的是, OAuthConsumer本身自己就支持一大堆國外的OAuth, 并且在我看來代碼都是沒有什么問題的, 到了國內(nèi), 標(biāo)準(zhǔn)就不是標(biāo)準(zhǔn)了,標(biāo)準(zhǔn)只是參考, 各家各戶按照自己的理解在做。
國內(nèi)的互聯(lián)網(wǎng)環(huán)境真的是相當(dāng)有特色的,對此,面對需求和計(jì)劃,我只能說,先實(shí)現(xiàn)功能吧,代碼寫成什么樣先不說了。
國內(nèi)的開發(fā)環(huán)境也是比較混亂,因?yàn)榛径际谴a抄來抄去,有時候并沒有真正的去實(shí)現(xiàn),可以想象,服務(wù)端的協(xié)議制作應(yīng)該也是一樣的,做協(xié)議的總是不能夠靜下心來做事。
由于時間比較緊,我承認(rèn)我偷懶使用了很多現(xiàn)有的代碼。也因?yàn)檫@樣,讓這個庫的功能還不是那么完整,還有很多不是能夠比較好的支持。中間百般折騰,給我造成了很多的困擾,自此,也就是支持新浪,騰訊,搜狐,網(wǎng)易,豆瓣和人人的授權(quán)。其他的還需要改進(jìn)。
浙公網(wǎng)安備 33010602011771號