OAuth 2.0授權框架詳解


簡介

在現代的網站中,我們經常會遇到使用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的博客

歡迎關注我的公眾號:「程序那些事」最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM