為什么需要oAuth
如果你接觸網絡的時間比較早,你應該能體會到網站注冊登錄方式的變化:
- 早期需要你輸入用戶名,密碼,然后要輸入郵箱,基于郵件來完成注冊驗證,然后使用用戶名密碼來登錄。因為當時郵箱是相對比較普及的。我當時在大學里學習計算機,老師布置的第一個任務就是去注冊個郵箱。
- 后來手機普及了,網站注冊登錄的方式是輸入手機號,收到驗證碼來驗證注冊登錄
- 再后來,可以直接基于微信、微博、QQ三方授權的方式來進行登錄
你會發現,注冊登錄的方式越來越簡單:
- 在早期你必須在每個你需要登陸的網站來注冊賬號密碼,相同的賬號密碼吧,怕被盜了一個密碼,其它全部被盜。不同的賬號密碼吧,記起來又費勁。后來出現了專門幫人管理密碼的軟件,不記得叫什么了。
- 使用手機號碼的方式,你可以基于驗證碼來進行臨時登錄,不過每次輸入驗證碼也挺麻煩的
- 三方授權的方式(也就是oAuth)只需要點擊確定授權,即可以登錄訪問,免去了注冊、驗證、再登陸的麻煩
可以看出,現在微信、微博、QQ這些用戶基數大的軟件,替代了當初的郵箱、手機,變成了注冊登錄的基礎設施。而且更加的安全:
- 通過郵箱注冊,假設你訪問了一些不正經的網站,郵箱被泄露后,會收到一堆垃圾郵件
- 通過手機號注冊,手機號被泄露后,會收到一堆的騷擾電話
- 而oAuth不會存在泄露的問題,除非微信、微博、QQ泄露了你的信息!
同時你也不需要記一堆亂七八糟的密碼了,只需要記著微信、微博、QQ的賬號密碼就可以了。
另一方面,對開發者來說,也省去了對賬號體系的管理,只需要遵循oAuth規范來接入微信、微博、QQ即可,降低了開發成本。
了解了oAuth的作用,我們來看一看oAuth的實現。
oAuth的概念
前段時間閱文集團合同事件鬧得沸沸揚揚,其中一個主要的問題就是資源所屬問題,合同里規定作者寫的作品歸閱文集團所有!網友立馬就炸了,那作品到底歸作者所有還是閱文集團所有呢?oAuth協議里已經給出了答案。
oAuth定義了四個角色:
- 資源擁有者(resource owner):絕大部分情況下,指的是用戶。
- 資源服務器(resource server):指的是服務提供商用來提供服務的服務器。
- 客戶端(client):即三方應用,需要用戶來授權訪問的應用
- 授權服務器(authorization server):即服務提供商專門用來處理授權認證的服務器。
OAuth 2.0的運行流程如下圖:

假設我們要通過閱文來登錄一個第三方網站:
- 「資源擁有者」打開「網站」以后,該「網站」要求「資源擁有者」給予授權
- 「資源擁有者」同意「網站」授權,「網站」接收到授權憑證。這里的授權方式取決于「網站」請求方式以及「授權服務器」所支持的方式。oAuth2.0協議里定義了四種方式,包括:授權碼模式、簡化模式、密碼模式和客戶端模式,后面會具體說明。當然也可以自定義。
- 「網站」使用上一步獲得的授權,向「認證服務器」申請令牌
- 「認證服務器」對「網站」進行認證以后,確認無誤,同意發放令牌
- 「網站」使用令牌,向「資源服務器」申請獲取資源
- 「資源服務器」確認令牌無誤,同意向「網站」開放資源
流程里很明顯:
- 「網站」就是Client
- 「認證服務器」就是AuthorizationServer,屬于閱文
- 「資源服務器」就是ResourceServer,也屬于閱文
- 而「資源擁有者」指的就是用戶。你用閱文集團來替換「資源擁有者」,就會發現流程明顯有問題。
從上面的流程可以看出,整個流程中「三方網站」沒有獲取到用戶的任何敏感信息,且獲取的信息需要用戶主動授權后才能獲取到,保證了安全性和便利性。
oAuth的分類
下面來一個個的說明具體的授權模式。在開始之前,需要多理解幾個概念:
- User-Agent:用戶代理,絕大部分情況下可以直接理解為瀏覽器
- Web Hosted Client Resource:網絡托管的客戶端資源,這里可以理解為托管網絡腳本的服務器
授權碼模式(Authorization Code Grant)

授權碼模式是功能最完整、流程最嚴密的授權模式。它通過Client的后臺服務器,與「服務提供商」的認證服務器進行互動置換token。具體流程如下:
- 「用戶」基于瀏覽器訪問「客戶端」,「客戶端」重定向到「認證服務器」對應頁面,引導的參數上會附帶一個「重定向URI」,指向的是「客戶端」頁
- 「用戶」選擇是否授權
- 授權后,「認證服務器」根據「重定向URI」將瀏覽器引導回「客戶端」頁,同時會附帶一個授權碼
- 「客戶端」接收到授權碼后,通過后臺服務器,攜帶這個授權碼以及「重定向URL」,向「認證服務器」申請令牌
- 「認證服務器」校驗無誤后,向「客戶端」發送令牌(AccessToken)和更新令牌(RefreshToken)
更新令牌(RefreshToken)的作用下文說明
簡化模式(Implicit Grant)

簡化模式不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了"授權碼"這個步驟。所有步驟在瀏覽器中完成,令牌對用戶是可見的,且客戶端不需要認證。具體流程如下:
- 「用戶」基于瀏覽器訪問「客戶端」,「客戶端」重定向到「認證服務器」對應頁面,引導的參數上會附帶一個「重定向URI」,指向的是「客戶端」頁
- 「用戶」選擇是否授權
- 授權后,「認證服務器」根據「重定向URI」將瀏覽器引導回「客戶端」頁,在URI的Fragment中會附帶訪問令牌
- 「客戶端」瀏覽器根據指令向「Web Hosted Client Resource」發送請求,該請求不包括上一步收到的Fragment,瀏覽器本地保存Fragment
- 「Web Hosted Client Resource」返回一個網頁(通常是一個包含腳本的網頁,如果你理解JSONP,應該比較容易理解),這段腳本是可以從Fragment中解析出訪問令牌的
- 瀏覽器執行腳本獲取令牌
- 瀏覽器將令牌發放給客戶端
密碼模式(Resource Owner Password Credentials Grant)

相對于上面兩種授權模式,密碼模式相對的不安全,因為用戶需要向客戶端提供自己的用戶名和密碼。客戶端使用這些信息,向"服務商提供商"索要授權。雖然協議里規定客戶端不能存儲賬號密碼,不過除非你非常信任客戶端,否則應該不會使用這種模式。
這種授權模式的具體流程如下:
- 「用戶」向「客戶端」提供用戶名和密碼
- 「客戶端」將用戶名和密碼發送給「認證服務器」,請求令牌
- 「認證服務器」驗證后,返回訪問令牌
客戶端模式(Client Credentials Grant)

客戶端模式下,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務提供商"提供服務。具體流程如下:
- 「客戶端」向「認證服務器」進行身份認證,并要求一個訪問令牌
- 「認證服務器」驗證后,返回訪問令牌
更新令牌
在上面的流程中,認證服務器認證后返回的數據,除了訪問令牌,還有一個更新令牌。我們知道了,通過訪問令牌我們才能夠訪問資源,那更新令牌是做什么用的呢?
我們都知道,一般網站登錄會有一個超時時間,這里也不例外。訪問令牌也有一個超時時間。更新令牌就是用于在訪問令牌過期后來獲取新的訪問令牌的。

- 「客戶端」向「授權服務器」進行認證,獲取access token。
- 「授權服務器」驗證「客戶端」后,發放訪問令牌和刷新令牌。
- 「客戶端」攜帶訪問令牌向「資源服務器」請求資源
- 「資源服務器」驗證訪問令牌,如果有效,則提供服務。
- 重復步驟3和4直到訪問令牌到期
- 當訪問令牌無效,「資源服務器」返回無效的令牌錯誤
- 「客戶端」向授權服務器進行身份驗證,并攜帶刷新令牌來請求新的訪問令牌
- 「授權服務器」驗證「客戶端」身份以及刷新令牌,如果有效,則發出新的訪問令牌(以及可選的新刷新令牌)
最后補充
在上面的流程中,實際還缺少了一步,就是注冊客戶端。如果你接過微信、微博或QQ的授權登陸,那么應該清楚,在開始接入之前,我們需要在他們的開放平臺上申請我們的應用,申請成功后會給我們一個AppId和一個appSecrect。
這個的appId就是用來唯一確定客戶端的。而appSecrect就是在授權模式中,客戶端的后臺與授權服務器交互時需要連同code,appId一起提供的,用于置換訪問令牌的。
總結
本文解釋了oAuth的作用,并梳理了oAuth的具體流程。
參考文檔
- 《The OAuth 2.0 Authorization Framework》https://www.ietf.org/rfc/rfc6749.txt