有兩家互聯網企業 A 和 B,其中 B 是一家提供相片雲存儲的公司。用戶可以把相片上傳到 B 網站上長期保存,然后可以在不同的設備上查看。某一天,A 和 B 談成了一項合作:希望用戶在使用 A 的客戶端時,也可以觀看他在 B 的相片。這個技術上要怎么實現呢?
選項一:由 B 提供一個接口:
GET /photos?account=
參數:
account : B 賬號
返回:
指定賬號下的所有相片
有了這個接口,A 的客戶端只需在界面上顯示一個輸入框,讓用戶輸入他的 B 賬號,然后調用這個接口來獲取相片就可以了。
這樣可行嗎?
NO!為啥?
因為實現並開放這樣一個接口,相當於直接把 B 公司的相片資源全部暴露在互聯網中,雖然並沒有公開,但是對於有點安全意識的技術人員來說,要發現這個接口簡直輕而易舉。這樣的話,B 的用戶就沒有任何隱私了。
那怎么辦呢?這樣吧,為了保證不能隨便獲取別人的相片,我們把接口改成這樣:
GET /photos?account=&pwd=
除了要求用戶輸入賬號,還要輸入密碼。只有當賬號密碼驗證通過,才返回該賬號下的所有相片。這樣,即使黑客發現了這個接口,他不知道用戶的密碼,所以沒辦法竊取用戶的相片了。這樣 OK 了吧?
答案還是 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 的交互模型的核心是這個樣子的:
解釋一下幾個術語。
資源服務器。即資源的存放地點,或者說資源的訪問入口。在例子中,資源服務器即 getPhoto 接口所部署的服務器。客戶端必須經由這里去訪問資源。
鑒權服務器。這是一個對用戶的身份進行認證、並對客戶端進行授權的地方。這也是 Oauth2.0 的關鍵節點。通常情況下,鑒權服務器也是屬於 B 公司的。
好,接下來看看整個交互過程是怎樣的。
首先,同樣是 B 的用戶在使用 A 的軟件,然后,A 需要訪問 B 用戶的相片。這個時候,A 並不是展示一個輸入框給用戶,而是打開一個頁面。這個頁面就是 B 部署在鑒權服務器上面的一個鑒權頁面,通常情況下,它長得類似下面這個樣子:
上面這個是騰訊給有道雲筆記進行授權的頁面。(是不是很熟悉?在哪見過?有興趣了解一下賬號接出的原理,其實就是Oauth2.0。)
這個頁面有兩個要素:
1,有認證機制。在騰訊這個例子中,你需要輸入QQ賬號密碼,證明你是一個合法的QQ用戶
2,展示了授權信息。看頁面右方“有道雲筆記將獲得以下權限”部分。這是在告訴用戶,如果你授權給客戶端,那么,客戶端將獲得訪問你這些資源的權限
注意,這個頁面是部署在 B 的鑒權服務器上,所有用戶輸入的賬號密碼是直接提交給 B,A 是沒有任何機會拿到的。
如果用戶同意授權並且認證通過,那么,接下來鑒權服務器會通知 A,並給 A 發送一個訪問令牌(access token,其實就是一段全局唯一的隨機字符串)。有了這個訪問令牌,A 就可以拿着它去找資源服務器要資源了。
所以,獲取相片的接口會是類似這個形式:
GET /photos?accesstoken=
資源服務器在接收到這個請求之后,會拿着 access token,再去找鑒權服務器,檢查這個 access token 的合法性和權限,如果通過的話,才返回資源給客戶端。
如此,即實現了功能,也保障了安全性。不過你可能會問,這個 access token 和賬號密碼的區別是什么呢?都是代表用戶身份的,為什么 access token 就更安全?答案是:
1,賬號密碼是一切,有了賬號密碼就幾乎可以做任何事情(甚至改掉原密碼)。而 access token 是有限制范圍的。每個 access token 都有一個 scope,也就是允許執行哪些操作。
2,access token 是有有效期的。如果 access token 被竊取,也不能一直用。
若有疑問,可以直接評論。