假設有兩家互聯網企業 A 和 B,其中 B 是一家提供相片雲存儲的公司。即 B 的用戶能夠把相片上傳到 B 網站上長期保存,而後能夠在不一樣的設備上查看。某一天,A 和 B 談成了一項合做:但願 B 用戶在使用 A 的客戶端時,也能夠觀看他在 B 的相片。假設你是技術負責人,須要出一個實現方案,怎麼作?安全
要不讓 B 提供一個接口:服務器
http://xxx.xxx.com/getPhoto?account=網站
參數:token
account : B 帳號接口
返回:資源
指定帳號下的全部相片部署
有了這個接口,A 的客戶端只需在界面上顯示一個輸入框,讓用戶輸入他的 B 帳號,而後調用這個接口來獲取相片就能夠了。get
這樣可行嗎?原理
NO!爲啥?軟件
由於實現並開放這樣一個接口,至關於直接把 B 公司的相片資源所有暴露在互聯網中,雖然並無公開,可是對於有點安全意識的技術人員來講,要發現這個接口簡直垂手可得。這樣的話,B 的用戶就沒有任何隱私了。
那怎麼辦呢?這樣吧,爲了保證不能隨便獲取別人的相片,咱們把接口改爲這樣:
http://xxx.xxx.com/getPhoto?account=&pwd=
除了要求用戶輸入帳號,還要輸入密碼。只有當帳號密碼驗證經過,才返回該帳號下的全部相片。這樣,即便黑客發現了這個接口,他不知道用戶的密碼,因此沒辦法竊取用戶的相片了。這樣 OK 了吧?
可能對於不少從沒有接觸過 Oauth 協議的人來講,這樣說就已經沒什麼問題了。可是,實際上答案仍是 NO!毫不能夠這麼作!
爲何?這裏涉及到一個信任問題。若是這樣實現,那麼,用戶必須在 A 的軟件裏輸入他在 B 的帳號和密碼。若是你是一個隱私意識很強的人,你極可能會問:「憑什麼我要把 B 的帳號密碼告訴 A ?」這裏,從用戶的角度就已經感覺到一種不安全感,憑什麼讓我信任你 A,你保證不拿個人 B 帳號密碼去幹壞事?而更深一層次,站在 B 的角度來考慮的話,也是同樣的問題:我憑什麼絕對信任 A?若是 A 在接收到用戶的輸入以後,立刻就把請求發到咱們這裏來,那是 ok 的。可是萬一 A 在這個過程偷偷把帳號密碼存起來了呢?那隨着時間的推移,A 就慢慢地蒐集到一大批 B 的帳號密碼!這對 B 來說,是不能接受的!
那怎麼辦呢?
咱們分析一下這個問題產生的緣由,主要是在於 A、B、用戶 三方的交互模型有問題。請看:
在這個場景下,用戶須要訪問他在 B 的相片資源,可是他不能直接和 B 打交道,而是必須經過 A。在這個前提下去考慮問題,不管如何沒法想出一個既能實現功能,又能讓用戶和 B 都感到放心的實現方案。
Oauth2.0 就是爲了解決這個問題而提出來的交互模型。它告訴人們,在這種場景下,三方要怎麼打交道,才能作到安全、合理。
具體來講,Oauth2.0 的交互模型的核心是這個樣子的:
解釋一下這幾個術語。
資源擁有者即用戶。
客戶端,泛指全部須要訪問資源的軟件實體。在咱們上面舉的例子中,資源即 B 用戶的相片。A 要訪問 B 用戶的相片,那麼 A 就是一個客戶端。
資源服務器。即資源的存放地點,或者說資源的訪問入口。在例子中,資源服務器即 getPhoto 接口所部署的服務器。客戶端必須經由這裏去訪問資源。
鑑權服務器。這是一個對用戶的身份進行認證、並對客戶端進行受權的地方。這也是在咱們的例子中所沒有的一個節點。一般狀況下,鑑權服務器也是屬於 B 公司的。
好,接下來看看整個交互過程是怎樣的。
首先,一樣是 B 的用戶在使用 A 的軟件,而後,A 須要訪問 B 用戶的相片。這個時候,A 並非展現一個輸入框給用戶,而是打開一個頁面。這個頁面就是 B 部署在鑑權服務器上面的一個鑑權頁面,一般狀況下,它長得相似下面這個樣子:
上面這個是騰訊給有道雲筆記進行受權的頁面。(是否是很熟悉?在哪見過?有興趣瞭解一下帳號接出的原理,其實就是Oauth2.0。)
這個頁面有兩個要素:
1,有認證機制。在騰訊這個例子中,你須要輸入QQ帳號密碼,證實你是一個合法的QQ用戶
2,展現了受權信息。看頁面右方「有道雲筆記將得到如下權限」部分。這是在告訴用戶,若是你受權給客戶端,那麼,客戶端將得到訪問你這些資源的權限
注意,這個頁面是部署在 B 的鑑權服務器上,全部用戶輸入的帳號密碼是直接提交給 B,A 是沒有任何機會拿到的。
若是用戶贊成受權而且認證經過,那麼,接下來鑑權服務器會通知 A,並給 A 發送一個訪問令牌(access token)。有了這個訪問令牌,A 就能夠拿着它去找 資源服務器要資源了。
因此,獲取相片的接口會是這個形式:
http://xxx.xxx.com/getPhoto?accesstoken=
資源服務器在接收到這個請求以後,會拿着 access token,再去找鑑權服務器,檢查這個 access token 的合法性和權限,若是經過的話,才返回資源給客戶端。