OAuth 2.0 理解
OAuth 是一個用于定于授權的開放標準,目前已經發展到了 2.0 的版本。它可以讓用戶允許第三方應用程序訪問該用戶存儲在某一個網站或者系統上面的資源(比如照片,聯系人)而不用提供密碼給該第三方應用程序,并且還可以限制權限和有效期。OAuth 做到了一下這兩點:
-
不需要將用戶名和密碼提供給第三方應用而是通過令牌讓第三方應用訪問資源
-
每一個令牌授權一個特定的應用在特定的時段內訪問特定的資源
應用場景
OAuth 的應用場景遍布互聯網應用的方方面面,最典型的就是微博。比如我們在開發一個第三方的微博客戶端(下文簡稱為:客戶端),需要可以登錄用戶并且操作用戶的一系列微博信息。最簡單的辦法就是把微博賬號密碼告訴這個客戶端,但是這樣就會存在一系列的問題:
-
客戶端為了后續的服務,會保存用戶的密碼,這樣不安全
-
客戶端擁有了客戶微博的權力,用戶沒法限制授權的范圍和有效期
-
用戶只有修改密碼,才能收回權限,但是這樣會使得其他的第三方應用程序失效
除了這些還會導致只要有一個第三方應用程序被破解,就會導致用戶密碼泄漏,以及所有被密碼保護的數據泄漏。而且 OAuth 就是來解決這個問題的。
理解 OAuth
在理解 OAuth 之前,需要說明幾個名詞:
-
Client:第三方應用程序,就是本文中的客戶端
-
Resource owner : 資源所有者,本文中稱為"yonghu"。
-
Authorization server :認證服務器,服務提供商專門用來處理認證的服務器
-
Resource server:資源服務器,服務提供商存放用戶生成的資源的服務器,它和認證服務器,可以是同一臺服務器,也可以是不同的服務器。
來看看流程圖:
整個授權流程按照順序分為六個步驟:
-
用戶打開客戶端以后,客戶端要求用戶給予授權
-
用戶同意授權
-
客戶端使用上一步獲得的授權,向認證服務器申請令牌
-
認證服務器對客戶端進行認證以后,確認無誤并且發放令牌
-
客戶端使用令牌向資源服務器申請獲取資源
-
資源服務器確認令牌無誤同意向客戶端開放資源
授權模式
OAuth 2.0 總共定義了 4 中授權模式,分別是以下四種:
-
授權碼模式
-
簡化模式
-
密碼模式
-
客戶端模式
授權碼模式
其中授權碼模式是功能最完整,流程最嚴密的授權模式。授權流程圖:
首先用戶打開客戶端應用,這時候客戶端要求進行授權并且會跳轉到授權頁面:
我們可以看到跳轉到的授權 URL 是這樣的:
-
https://api.weibo.com/oauth2/authorize :認證服務器
-
client_id :客戶端的 client id,用于給認證服務器識別該客戶端
-
redirect_uri :獲得授權碼之后,認證服務器重定向用戶代理(比如瀏覽器)的地址
-
response_type : 表明授權類型,默認是 code,即授權碼模式
-
state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值,用于抵御 CSRF 攻擊
這時候用戶同意進行授權,認證服務器將用戶跳轉到客戶端事先指定的 redirect_uri, 同時附上一個授權碼
客戶端收到授權碼,附上之前的 redirect_uri 向認證服務器申請令牌,這一步是在客戶端的后臺服務器上完成的,對用戶不可見。比如:
-
https://api.weibo.com/v1/oauth2/authorize :獲取 access_token 的服務器地址
-
client id :client id 用于驗證應用程序。
-
client secret:client secret 用于驗證應用程序。
-
grant_type :剛剛獲得的授權碼
-
redirect_uri :重定向URI,和第一步一致
認證服務器確認無誤后,向客戶端發送訪問令牌和更新令牌:
這個返回的包括了以下這些,有些還有包含一個權限范圍 scope,這里不撰述:
-
access_token:訪問令牌
-
token_type :令牌類型
-
expires_in :過期時間,單位為秒
-
refresh_token: 更新令牌,用來獲取下一次的訪問令牌
簡化模式
簡化模式不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了授權碼這個步驟,所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證。這種模式一般是用于手機應用,桌面客戶端應用程序和運行于瀏覽器上的 Web 應用程序, 授權令牌會交給用戶代理,再由用戶代理交給應用程序。如下圖:
-
首先用戶訪問客戶端,客戶端將用戶導向認證服務器, 并且用戶選擇同意授權:
-
認證服務器將用重定向客戶端事先指定的 URI,并且在 URI 的 hash 部分包含了訪問令牌:
-
瀏覽器向資源服務器發出請求,其中不包括上一步收到的 hash 值
-
資源服務器返回一個網頁,其中包含的代碼可以獲取 hash 值中的令牌
-
瀏覽器執行上一步獲得的腳本并且取出令牌
-
瀏覽器將令牌發送給客戶端
密碼模式
用戶向客戶端提供用戶名密碼,客戶端使用這些信息,向 服務商提供商 索要授權。在這種模式下,客戶端不得存儲密碼。 這通常用在用戶對客戶端高度可信的情況下 , 一般認證服務器只有在其他授權模式無法執行的情況下,并且客戶端是由某一個著名公司出品才能考慮使用這種模式。如下圖:
-
用戶向客戶端提供用戶名和密碼
-
客戶端將用戶名和密碼發給認證服務器,向后者請求令牌
-
認證服務器確認無誤后,向客戶端提供訪問令牌
客戶端模式
客戶端使用自己的名義而不是用戶的名義,向服務提供商進行認證。在這種模式下,用戶直接向客戶端注冊,客戶端以自己的名義要求服務提供商提供服務,其實并不存在授權。如下圖:
對于這種方式,用在訪問一些和用戶無關的公共接口,比如一些首頁數據,這些數據和用戶無關,但是又不想任何人都可以調用這個 Api,那么就可以采用這種模式。
刷新令牌
認證服務器頒發的令牌是有有效期限制的,所以客戶端需要自行去刷新令牌。如果用戶訪問的時候,客戶端的訪問令牌已經過期,則需要使用更新令牌申請一個新的訪問令牌。客戶端通過一個POST 請求并且攜帶上參數:
-
granttype:表示使用的授權模式,此處的值固定為 refreshtoken,必選
-
refresh_token:表示早前收到的更新令牌,必選
-
scope:表示申請的授權范圍,不可以超出上一次申請的范圍,如果省略該參數,則表示與上一次一致
來自:http://mp.weixin.qq.com/s/hzy8gV0eDdumg0TD5mi5cA