Python-Web開發 OAuth2.0 簡介


  • 經常看到或者用到一些可以使用微博、微信、支付寶等賬號登錄的應用,還有一些微博助手、微信公眾號助手、客戶端之類的東西,這些是怎么做的呢,背后的原理是什么呢?為什么公眾號配置起來那么繁瑣呢?什么是 access token、refresh token?等等,今天我們來了解下開放式授權模式 OAuth
  • 隨着互聯網的發展,各種應用相互交叉,到處需要用戶登錄,信息安全成為了不可回避的問題,應用需要擴展,用戶需要更好的體驗,信息需要更安全的保障,為了滿足這些需求,互聯網技術不斷推陳出新,從通信安全,到各種協議框架,有無數的解決方案。
  • OAuth 是什么

    OAuth 框架提供了一種認證和授權機制,可以讓用戶將其受保護的資源授權給其他應用來訪問或者使用。

  • 授權機制相當於你給快遞員一個臨時密碼(授權),快遞員可以使用這個密碼打開小區門禁,將快遞送到你家門口,而后臨時密碼將失效(詳見參考鏈接)
  • 這個例子中,你就是 用戶,小區是 受保護的資源,快遞員是其他應用(第三方應用)。
  • 如果沒有這個機制:

    • 要么你就得去小區門口拿快遞,不方便,
    • 要么就得告訴所有可能給你送快遞的快遞員門禁密碼,不安全

    有了 OAuth 框架(協議),既方便,又安全

  • 角色

    OAuth2.0 實際上就是讓第三方服務獲得用戶在資源服務器上的授權的過程,會涉及到 4 種角色

    • 資源擁有者(Resource owner),即用戶
    • 認證服務器(Authorization server),用來認證用戶憑證,頒布授權碼的服務器
    • 資源服務器(Resource Server),存放用戶受保護的資源的服務器
    • 第三方應用(Client),也稱之為客戶端(后續皆稱 客戶端),需要得到用戶授權,以便訪問用戶受保護的資源的應用程序

    不是任何客戶端都能得到授權的,在開通 OAuth 授權之前,需要先到認證服務器或者資源服務器上注冊,注冊成功會得到 appid 和 app_secret,用來向認證服務器表明應用的身份

    角色之間關聯

    了解了 OAuth2.0 框架中的主要角色,有必要了解下角色之間關聯關系

    • 認證服務器 和 資源服務器:通常來說,認證服務器和資源服務器同屬於一個服務商,它們就有天生的關聯,而且是內部的安全的,甚至它們可以部署在同一個服務器(Web 服務器)上
    • 用戶 和 服務商:對於像 Github、微信這樣的知名應用,用戶會主動在這些應用或服務上注冊,填寫的資料信息,設置的昵稱,產生的文章、上傳的照片,等等將成為用戶的資源,這些資源被存放在資源服務器上
    • 客戶端 和 服務商:客戶端,即第三方應用,要從服務商的資源服務器中獲取數據,給用戶提供額外服務,必須在服務商處注冊,提供應用的基本信息,認證信息,服務域名,申請用戶授權的范圍、甚至企業資質(例如申請微信公眾號的企業服務)等等,申請通過后,服務商會返回 appid 和 app_secret,作為客戶端和服務商的交互憑證
    • 用戶 和 客戶端:客戶端提供了特別的服務,可以吸引到用戶,為了讓用戶體驗更好,引導用戶通過授權的方式,從而獲取授權范圍內的用戶信息,例如 Openid,作為用戶在客戶端上的唯一標識,從而建立起和用戶的關聯

    至此,四個角色之間的關聯就建立好了,下面開始介紹具體的授權方式

  • 基本授權流程

     

  •  

     

  • 沒有比圖更能說明白流程的,借用 RFC6749 文檔

    授權流程圖
    • A 客戶端,向用戶發出授權請求
    • B 用戶同意或者拒絕客戶端的授權請求,假設是同意
    • C 客戶端拿着用戶的授權請求認證服務器做認證
    • D 如果 C 通過認證,認證服務器將返回 Access Token,即可以訪問資源的令牌
    • E 客戶端使用 Access Token 請求資源服務器上的資源
    • F 資源服務器驗證了 Access Token 后,返回受保護的資源

    流程中最核心的是讓客戶端獲得 Access Token,之后在訪問受保護資源時,就不需要用戶反復授權了

    Access Token 顯然不是用戶在資源服務器上的密碼,是有認證服務器頒發的,那么也可以被銷毀

    Access Token 和之前課程中的 JWT 是類似的,實際上 JWT 是 OAuth 認證的一個特例

    授權模式

    根據授權流程,OAuth2.0 定義了 4 種針對不同應用場景的授權模式

    • 授權碼模式(authorization code)
    • 簡化模式(implicit)
    • 密碼模式(resource owner password credentials)
    • 客戶端模式(client credentials)

    授權碼模式

    授權碼模式是最完整,安全性最高的授權模式,也是最常用的一種模式,其特點是通過客戶端的后台服務器與認證服務器交互,如圖:

     

     

    授權碼模式流程圖

    注意:上圖中的步驟 A, B, C 在通過用戶代理端( User-Agent 一般指瀏覽器)時,被拆分成了兩部分

    • A 用戶訪問客戶端的客戶端,后者將前者導向認證服務器
    • B 用戶確定是否授權給客戶端
    • C 假設用戶給予授權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(Redirection URI),同時附上一個授權碼
    • D 客戶端收到授權碼,通過后台服務器,附上早先的"重定向URI",向認證服務器申請令牌。這一步對用戶不可見
    • E 認證服務器核對了授權碼和重定向URI,確認無誤后,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)

    接下來說明一下過程中所包含一下參數

    不同認證服務器上的參數名稱有可能不同,但含義相同,例如 client_id 一般被 appid 代替

    步驟 A,客戶端申請認證的 URI,包含以下參數:

    • response_type:表示授權類型,必選項,此處的值固定為 code,因為需要先獲取授權碼
    • client_id:表示客戶端的ID,必選項,是在認證服務器分配給客戶端的id,即 appid
    • redirect_uri:表示重定向URI,可選項
    • scope:表示申請的權限范圍,可選項
    • state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值

    步驟 C,認證服務器回應的 URI,包含以下參數:

    • code:表示授權碼,必選項。該碼的有效期應該很短,通常設為 10 分鍾,客戶端只能使用該碼一次,否則會被認證服務器拒絕。該碼與客戶端 ID 和重定向 URI,是一一對應關系
    • state:如果客戶端的請求中包含這個參數,認證服務器的回應也必須一模一樣包含這個參數

    步驟 D,客戶端向認證服務器申請令牌的 HTTP 請求,包含以下參數:

    • grant_type:表示使用的授權模式,必選項,此處的值固定為 authorization_code
    • code:表示上一步獲得的授權碼,必選項
    • redirect_uri:表示重定向 URI,必選項,且必須與 A 步驟中的該參數值保持一致
    • client_id:表示客戶端 ID,必選項

    步驟 E,認證服務器發送的 HTTP 響應,包含以下參數:

    • access_token:表示訪問令牌,必選項
    • token_type:表示令牌類型,該值大小寫不敏感,必選項,可以是bearer類型或mac類型
    • expires_in:表示過期時間,單位為秒。如果省略該參數,必須其他方式設置過期時間
    • refresh_token:表示更新令牌,用來獲取下一次的訪問令牌,可選項
    • scope:表示權限范圍,如果與客戶端申請的范圍一致,此項可省略

    認證服務器會以 JSON 的形式返回 access_token 數據,且不允許做緩存,以提高安全性

    簡化模式

    簡化模式不需要通過客戶端后台服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了授權碼這個步驟,因此得名。所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證,如圖:

     

     

    簡化模式流程圖
    • A 客戶端將用戶導向認證服務器
    • B 用戶決定是否給予客戶端授權
    • C 假設用戶給予授權,認證服務器將用戶導向客戶端指定的重定向URI,並在URI的Hash部分包含了訪問令牌 access_token
    • D 瀏覽器向資源服務器發出請求,其中不包括上一步收到的Hash值
    • E 資源服務器返回一個網頁,其中包含的代碼可以獲取Hash值中的令牌
    • F 瀏覽器執行上一步獲得的腳本,提取出令牌
    • G 瀏覽器將令牌發給客戶端

    接下來說明一下過程中所包含一下參數

    步驟 A,客戶端發送 HTTP 請求,包含的參數:

    • response_type:表示授權類型,此處的值固定為 token,必選項
    • client_id:表示客戶端的ID,必選項
    • redirect_uri:表示重定向的URI,可選項
    • scope:表示權限范圍,可選項
    • state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值

    步驟 C,認證服務器回應客戶端的 URI,包含以下參數:

    • access_token:表示訪問令牌,必選項。
    • token_type:表示令牌類型,該值大小寫不敏感,必選項
    • expires_in:表示過期時間,單位為秒。如果省略該參數,必須其他方式設置過期時間
    • scope:表示權限范圍,如果與客戶端申請的范圍一致,此項可省略
    • state:如果客戶端的請求中包含這個參數,認證服務器的回應也必須一模一樣包含這個參數

    有個需要注意的地方,步驟 C,返回的 access_token 放在重定向 URL 的 Fragment 中,即錨點中, # 后面,例如

    http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA &state=xyz&token_type=example&expires_in=3600

    因為錨點中的內容不會發送給后台,從而減少了一次數據傳輸,降低了一定風險

    對於簡化模式獲得的 access_token 有效期很短,一般是會話級的,即當會話結束時就失效

    密碼模式

    密碼模式中,用戶向客戶端提供自己的用戶名和密碼,客戶端使用這些信息,向"服務商提供商"索要授權。

    在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼(既然用戶信任你,你就必須兌現這個承諾)。

    密碼模式的特性決定,需要用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統的一部分,或者由一個著名公司出品,而認證服務器只有在其他授權模式無法執行的情況下,才能考慮使用這種模式

    這里只簡單介紹下,不做做詳細講解,如有興趣了解,可以查閱文末參考

    客戶端模式

    客戶端模式指客戶端以自己的名義,而不是以用戶的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式並不屬於 OAuth 框架所要解決的問題

    在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務提供商"提供服務,其實不存在授權問題

    客戶端模式,就像二道販子(只為借用比喻,並無貶義),將原始服務包裝后,再提供給最終用戶,常見於多租戶的 Saas 系統,例如統一提供支付通道、處理 GPS 信息等

    這里也只簡單介紹下,如有興趣了解,可以查閱文末參考

    刷新 access_token

    在 授權碼模式中,授權服務器可以會同時返回 refresh_token,用來在 access_token 過期前,重新獲取新的access_token,不需要用戶重新確認授權,有助於提高用戶體驗

    在 access_token 過期前,客戶端可用 refresh_token 向授權服務器發送請求,例如,假設 b.com 是授權服務器地址,請求大體是:

    https://b.com/oauth/token? grant_type=refresh_token& client_id=CLIENT_ID& client_secret=CLIENT_SECRET& refresh_token=REFRESH_TOKEN
    • grant_type: 授權類型,值為 'refresh_token'
    • client_id: 客戶端 id,即第三方應用在授權服務器上注冊被分配的 id
    • client_secret: 客戶端和授權服務器通行的密鑰,由授權服務器頒發,在特殊需要確認的情況下需要作為驗證條件
    • refresh_token: 用戶獲取新的 access_token 的 refresh_token

    安全的 OAuth2.0

    上面較為詳細的講述了 OAuth2.0 框架,了解了在開放網絡中如何安全的獲取用戶授權的技術細節,但再完善的交互方案、再復雜的嚴密的通信過程,都避免不了中間人攻擊,當客戶端和認證服務器之間通過 http 協議交互數據時,會被截取通信內容,從而獲得用戶的授權,這是不能接受的,所以 OAuth2.0 需要建立在 https 協議上,將通信內容加密,最大程度的防止信息被竊取。

    如果 OAuth2.0 框架用在敏感信息交互上時,必須使用 https 協議確保安全,但並不是說只能支持 https,對於非敏感數據,或者不重要的授權,可以使用 http 協議作為通信方式

    總結

    本節課程着重介紹了 OAuth2.0 授權框架,從它的作用,到具體的技術細節,做了較為詳細的講述,如果需要用安全的授權,需要將通信建立在 https 協議之上。由於 OAuth 概念較多,流程復雜,這節沒有涉及到具體的編程實踐,下一節,我們以 Github 為例,使用之前介紹過的 Authlib 模塊,用 Flash 實現一個第三方應用,作為實踐,敬請期待


免責聲明!

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



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