簡介
在現代的網站中,我們經常會遇到使用OAuth授權的情況,比如有一個比較小眾的網站,需要使用者登入,但是直接讓使用者註冊就顯得非常麻煩,使用者可能因為這個原因而流失,那麼該網站可以使用OAuth授權,藉助於github或者其他的第三方網站的認證授權,來獲取相關的使用者資訊,從而避免了使用者註冊的步驟。
當然,很可能在第三方網站上授權獲得使用者資訊之後,還需要在本網站填寫一些必要的資訊進行繫結,比如手機號,使用者名稱等等。
但是這比單純的註冊要方便太多了,也容易讓使用者接受。
今天,我們將要講解一下OAuth 2.0授權框架的構成,希望大家能夠喜歡。
OAuth的構成
在傳統的CS模式的授權系統中,如果我們想要藉助第三方系統來訪問受限的資源,第三方系統需要獲取到受限資源伺服器的使用者名稱和密碼,才能進行對資源伺服器的訪問,很顯然這個是非常不安全的。
在OAuth2中,我們是怎麼做的呢?
我們先來看一下OAuth2中授權的流程圖:
一般來說OAuth2中有4個角色。
resource owner: 代表的是資源的所有者,可以通過提供使用者名稱密碼或者其他方式來進行授權。通常來是一個人。
resource server:代表的是最終需要訪問到資源的伺服器。比如github授權之後獲取到的使用者資訊。
client: 用來替代resource owner來進行互動的客戶端。
authorization server: 用來進行授權的伺服器,可以生成相應的Access Token。
整個流程是這樣的:
Client向resource owner發起一個授權請求,resource owner輸入相應的認證資訊,將authorization grant返回給client。
client再將獲取到的authorization grant請求授權伺服器,並返回access token。
client然後就可以拿著這個access token去請求resource server,最後獲取到受限資源。
refresh Token
為了安全起見,access token總是有過期時間的,那麼如果token過期了怎麼辦呢?
具體的辦法就是refresh Token :
我們看一下refresh token的流程圖:
前面的A,B,C,D和之前的講到的流程是一致的。
如果接下來訪問資源的時候,access token過期了,那麼client會再次向認證服務發出refresh token的請求。
然後認證伺服器會再次返回新的access token.
Authorization Code模式
上面我們講到的模式中,Client會儲存Authorization Grant資訊,並通過這個資訊來去授權伺服器請求Access Token。
Client直接儲存Authorization Grant資訊,並和授權伺服器進行通訊,這對client會有一定的安全限制。
如果是在web環境中,client是藉助user-agent(web瀏覽器)來進行訪問的該如何處理呢?
這裡向大家介紹一個Authorization Code模式。
Client通過User-Agent發起請求,並附帶跳轉連結。當提供了使用者的授權認證資訊之後,授權伺服器返回的不是token而是authorization code,拿到這個code之後,client可以通過這個code來獲取access Token或者refresh Token。
上面的授權流程圖我們可以通過一個具體的例子來說明,resource owner就是我們要訪問的資源。 Authorization Server是第三方的授權伺服器,比如github的授權服務。而User-Agent就是瀏覽器。
好了,我們開始具體流程的講解:
比如使用者想獲取www.flydean.com的資訊,但是需要登入,這個時候就跳轉到github的登入介面,我們輸入github的使用者名稱密碼,github會返回一個Authorization Code到我們的伺服器比如 www.flydean.com/?code=code, client拿到這個code之後,會去後臺請求github,去驗證這個code的合法性,如果code合法,則github會返回access token的資訊,client後面就可以通過access token去github資源伺服器資源了。
舉一個具體的access token返回值的例子:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
隱式授權
在上面我們講到的幾個模式中,client都需要直接和授權伺服器進行通訊,從而獲取到access Token,有沒有什麼方式可以不需要client和授權伺服器直接通訊就可以得到access token呢?
接下來我們講一下隱式授權。
上圖就是一個隱式授權的例子,和Authorization Code模式不同的是,授權伺服器返回的是一個access token片段,只有這個片段,我們是無法得到access token的。
這裡我們需要額外請求一次client resource伺服器,伺服器將會返回一個script指令碼,通過這個指令碼,我們對access token片段進行解析,得到最終的access token。
Resource Owner 授權密碼認證
這種模式一般出現在resource owner非常信任client的情況下。
我們先看一下流程圖:
這種模式實際上相當於使用者將密碼交給client保管,由client使用儲存好的使用者名稱密碼向授權伺服器請求資源。
Client 認證授權
這種模式下,client本身是有一定的授權範圍的,可以通過client認證授權,直接獲取到授權伺服器的access token。
github的OAuth2認證流程
上面講的通用流程中,其實很多角色都可以合併的。
接下來我們具體講解一下如何使用github的OAuth2進行授權。
要使用github的OAuth2,需要首先在github中進行OAuth服務的註冊。
點選註冊按鈕,輸入相應的資訊,我們就可以完成註冊了。
這裡比較重要的就是callback url,我們會通過這個callback url來傳遞授權資訊。
註冊成功之後,你會得到一個Client ID和Client Secret。
github的授權步驟分為三個部分:
使用者跳轉到github的認證頁面進行授權
在這一部分中,我們需要跳轉到github的授權頁面:
https://github.com/login/oauth/authorize
上面是跳轉頁面的連結,這個連結可以接下面幾個引數:
client_id: 必須的引數,是我們上面註冊app得到的client id。
redirect_uri: 可選引數,如果不設定,則會使用註冊的時候提供的callback uri。
login:可選引數,指定具體的認證使用者名稱。
scope:github中許可權的範圍。
state: 是一個隨機數,用來防止cross-site攻擊。
allow_signup: 是否允許在認證的時候註冊。
看一下跳轉的頁面:
使用者跳轉回要訪問的資源頁面
當使用者授權之後,就會調整到callback頁面,並帶上code:
http://www.flydean.com/login?code=b14a2dd57f11b2310f42
應用程式拿到code之後,通過呼叫下面的請求來獲取access token:
POST https://github.com/login/oauth/access_token
這個post請求需要帶上client_id,client_secret,code這三個必須的引數,還可以帶上兩個可選的引數redirect_uri和state。
預設情況下,我們會獲取到下面的響應資訊:
access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&token_type=bearer
應用程式拿到access token獲取到github使用者資訊
有了access token之後,我們需要將token放到請求head中,去請求使用者資訊:
Authorization: token OAUTH-TOKEN
GET https://api.github.com/user
總結
OAuth2是一個非常常用的協議,也非常的方便,主要目的就是可以使第三方伺服器可以獲得授權範圍內的使用者資訊。希望大家能夠喜歡。
本文作者:flydean程式那些事
本文連結:http://www.flydean.com/oauth-2-0-in-depth/
本文來源:flydean的部落格
歡迎關注我的公眾號:「程式那些事」最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!