很多網(wǎng)站、APP 弱化甚至沒(méi)有搭建自己的登陸頁(yè)面,而是直接使用社會(huì)化登錄的方式,這樣不僅免去了用戶(hù)注冊(cè)賬號(hào)的麻煩、還可以獲取用戶(hù)的好友關(guān)系來(lái)增強(qiáng)自身的社交功能。
比如我們可以使用微博登錄簡(jiǎn)書(shū),簡(jiǎn)書(shū)會(huì)自動(dòng)將你的微博頭像設(shè)置為你的簡(jiǎn)書(shū)頭像,將你的微博昵稱(chēng)設(shè)置為你的簡(jiǎn)書(shū)昵稱(chēng),甚至還可以獲取你微博中的好友列表,提示你哪些朋友已經(jīng)在使用簡(jiǎn)書(shū),這是如何做到的呢?
最傳統(tǒng)的辦法是讓用戶(hù)直接在簡(jiǎn)書(shū)的登錄頁(yè)面輸微博的賬號(hào)和密碼,簡(jiǎn)書(shū)通過(guò)用戶(hù)的賬號(hào)和密碼去微博那里獲取用戶(hù)數(shù)據(jù),但這樣做有很多嚴(yán)重的缺點(diǎn):
- 簡(jiǎn)書(shū)需要明文保存用戶(hù)的微博賬號(hào)和密碼,這樣很不安全。
- 簡(jiǎn)書(shū)擁有了獲取用戶(hù)在微博所有的權(quán)限,包括刪除好友、給好友發(fā)私信、更改密碼、注銷(xiāo)賬號(hào)等危險(xiǎn)操作。
- 用戶(hù)只有修改密碼,才能收回賦予簡(jiǎn)書(shū)的權(quán)限。但是這樣做會(huì)使得其他所有獲得用戶(hù)授權(quán)的第三方應(yīng)用程序全部失效。
- 只要有一個(gè)第三方應(yīng)用程序被破解,就會(huì)導(dǎo)致用戶(hù)密碼泄漏,以及所有使用微博登錄的網(wǎng)站的數(shù)據(jù)泄漏。
為了解決以上的問(wèn)題,OAuth 協(xié)議應(yīng)運(yùn)而生。
原理概要
新浪微博作為服務(wù)提供商,擁有用戶(hù)的頭像、昵稱(chēng)、郵箱、好友以及所有的微博內(nèi)容,簡(jiǎn)書(shū)希望獲取用戶(hù)存儲(chǔ)在微博的頭像和昵稱(chēng),假設(shè)它們是三個(gè)人:
- 簡(jiǎn)書(shū)問(wèn)新浪微博:我想要獲取用戶(hù) A 的頭像和昵稱(chēng),請(qǐng)你提供
- 微博說(shuō):我需要經(jīng)過(guò)用戶(hù)A 本人的許可,然后去問(wèn)用戶(hù) A 是否要授權(quán)簡(jiǎn)書(shū)訪(fǎng)問(wèn)自己的頭像和昵稱(chēng)
- 用戶(hù) A 對(duì)微博說(shuō):我給簡(jiǎn)書(shū)一個(gè)臨時(shí)的鑰匙,如果他給你出示了這把鑰匙,你就把我的資料給他
- 簡(jiǎn)書(shū)使用戶(hù)給它的鑰匙獲取用戶(hù)頭像和昵稱(chēng)信息。
以上是 OAuth 認(rèn)證的大概流程。在使用微博授權(quán)之前,簡(jiǎn)書(shū)需要先在微博開(kāi)放平臺(tái)上注冊(cè)應(yīng)用,填寫(xiě)自己的名稱(chēng)、logo、用途等信息,微博開(kāi)放平臺(tái)頒發(fā)給簡(jiǎn)書(shū)一個(gè)應(yīng)用 ID 和叫 APP Secret 的密鑰,在實(shí)際對(duì)接中,會(huì)使用到這兩個(gè)參數(shù)。
詳細(xì)流程

接下來(lái)分步詳細(xì)解釋上圖中每步都做了什么:
-
用戶(hù)點(diǎn)擊簡(jiǎn)書(shū)上的微博登錄按鈕,跳轉(zhuǎn)到微博授權(quán)頁(yè)面。微博登錄按鈕的鏈接形如下方的 URL:
https://api.weibo.com/oauth2/authorize?client_id=123050457758183&redirect_uri=http://jianshu.com/callback
URL 中要包含以下參數(shù):
* client_id:在微博開(kāi)放平臺(tái)申請(qǐng)的應(yīng)用 ID
* redirect_uri:授權(quán)成功后要跳轉(zhuǎn)到的地址
點(diǎn)擊以上鏈接后跳轉(zhuǎn)到微博的授權(quán)頁(yè)面如下圖:

這個(gè)頁(yè)面會(huì)告訴用戶(hù)第三方應(yīng)用要獲取用戶(hù)的哪些數(shù)據(jù),以及擁有什么權(quán)限,比如在上圖中簡(jiǎn)書(shū)會(huì)要求獲得個(gè)人信息、好友關(guān)系、分享內(nèi)容到微博以及獲得評(píng)論的權(quán)限,用戶(hù)點(diǎn)擊“允許”則表示允許簡(jiǎn)書(shū)獲得這些數(shù)據(jù),進(jìn)行下一步
-
頁(yè)面自動(dòng)跳轉(zhuǎn)到初始參數(shù)中
redirect_uri定義的那個(gè)URL,并自動(dòng)在 URL 末尾添加一個(gè)code參數(shù),實(shí)際跳轉(zhuǎn)的地址形如:http://jianshu.com/callback?code=2559200ecd7ea433f067a2cf67d6ce6c -
第三步,簡(jiǎn)書(shū)通過(guò)上一步獲取的 code 參數(shù)換取 Token,Token 就是前文中說(shuō)到的鑰匙。簡(jiǎn)書(shū)請(qǐng)求如下的接口獲取 Token:
POST https://api.weibo.com/oauth2/access_token
要包含以下參數(shù):- client_id:在微博開(kāi)放平臺(tái)申請(qǐng)的應(yīng)用 ID
- client_secret:在微博開(kāi)放平臺(tái)申請(qǐng)時(shí)提供的APP Secret
- grant_type:需要填寫(xiě)authorization_code
- code:上一步獲得的 code
- redirect_uri:回調(diào)地址,需要與注冊(cè)應(yīng)用里的回調(diào)地址以及第一步的 redirect_uri 參數(shù)一致
-
通過(guò)第三步的請(qǐng)求,接口返回 Token 和相關(guān)數(shù)據(jù):
{ "access_token": "ACCESS_TOKEN",//Token 的值 "expires_in": 1234,//過(guò)期時(shí)間 "uid":"12341234"http://當(dāng)前授權(quán)用戶(hù)的UID。 } -
在第四步中獲取了access_token ,使用它,就可以去獲取用戶(hù)的資源了,要獲取用戶(hù)昵稱(chēng)和頭像,請(qǐng)求如下接口:
GET https://api.weibo.com/2/users/show.json攜帶參數(shù):
- access_token:上一步獲取的access_token
- uid:用戶(hù)的賬號(hào) id,上一步的接口有返回
最后一步,微博返回用戶(hù)信息,簡(jiǎn)書(shū)進(jìn)行處理,整個(gè)流程結(jié)束。
通過(guò)以上的方式,在簡(jiǎn)書(shū)和新浪微博中間建立了一個(gè)獨(dú)立的權(quán)限層,這個(gè)權(quán)限由用戶(hù)賦予,可以被用戶(hù)隨時(shí)取消,不同第三方應(yīng)用之間相互獨(dú)立,互不干擾,這樣就徹底解決了明文存放賬號(hào)密碼的問(wèn)題。
以上只是以新浪微博為例,概括了一種最常見(jiàn)的 OAuth2.0 認(rèn)證方式,關(guān)于 OAuth 更全面的文檔,請(qǐng)參見(jiàn) RFC 6749。阮一峰博客上也寫(xiě)過(guò)一篇關(guān)于 OAuth 的科普,推薦閱讀:《理解OAuth 2.0》