一、基礎知識
1、OAuth產生背景
很多網站、APP 弱化甚至沒有搭建自己的賬號體系,而是直接使用社會化登錄的方式,這樣不僅免去了用戶注冊賬號的麻煩、還可以獲取用戶的好友關系來增強自身的社交功能。
比如我們可以使用微博登錄簡書,簡書會自動將你的微博頭像設置為你的簡書頭像,將你的微博昵稱設置為你的簡書昵稱,甚至還可以獲取你微博中的好友列表,提示你哪些朋友已經在使用簡書,這是如何做到的呢?
最傳統的辦法是讓用戶直接在簡書的登錄頁面輸微博的賬號和密碼,簡書通過用戶的賬號和密碼去微博那里獲取用戶數據,但這樣做有很多嚴重的缺點:
- 簡書需要明文保存用戶的微博賬號和密碼,這樣很不安全。
- 簡書擁有了獲取用戶在微博所有的權限,包括刪除好友、給好友發私信、更改密碼、注銷賬號等危險操作。
- 用戶只有修改密碼,才能收回賦予簡書的權限。但是這樣做會使得其他所有獲得用戶授權的第三方應用程序全部失效。
- 只要有一個第三方應用程序被破解,就會導致用戶密碼泄漏,以及所有使用微博登錄的網站的數據泄漏。
為了解決以上的問題,OAuth 協議應運而生。
2、定義
OAuth2.0(開放授權)是一個關於授權的開放的網絡協議。
--->允許用戶讓第三方應用訪問該用戶在某一網站上存儲的的資源(如:照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。
--->OAuth是一個關於授權(Authorization)的開放網絡標准,目前的版本是2.0版。注意是Authorization(授權),而不是Authentication(認證)。用來做Authentication(認證)的標准叫openid connect。
3、基本原理
OAuth在第三方應用與服務提供商之間設置了一個授權層。第三方應用不能直接登錄服務提供商,只能登錄授權層,以此將用戶與客戶端區分開來。第三方應用登錄授權層所用的令牌,與用戶的密碼不同。用戶可以在登錄授權的時候,指定授權層令牌的權限范圍和有效期。
第三方應用登錄授權層以后,服務提供商根據令牌的權限范圍和有效期,向第三方應用開放用戶資源。
4、作用
讓客戶端安全可控地獲取用戶的授權,與服務提供商之間進行交互。可以免去用戶同步的麻煩,同時也增加了用戶信息的安全。
5、常用應用場景
- 用OAuth來實現第三方應用對我們API的訪問控制;
- 登錄第三方應用(APP或網頁)時,經常會采用其他用戶登錄方式,比如QQ,微博,微信的授權登錄(QQ用戶登錄)。
6、協議流程
(A)用戶打開客戶端以后,客戶端要求用戶給予授權。
(B)用戶同意給予客戶端授權。
(C)客戶端使用上一步獲得的授權,向認證服務器申請令牌。
(D)認證服務器對客戶端進行認證以后,確認無誤,同意發放令牌。
(E)客戶端使用令牌,向資源服務器申請獲取資源。
(F)資源服務器確認令牌無誤,同意向客戶端開放資源。
不難看出來,上面六個步驟之中,B是關鍵,即用戶怎樣才能給於客戶端授權。有了這個授權以后,客戶端就可以獲取令牌,進而憑令牌獲取資源。
7、客戶端的授權模式
----客戶端獲取授權的四種模式
客戶端必須得到用戶的授權(authorization grant),才能獲得令牌(access token)。OAuth 2.0定義了四種授權方式。
- 授權碼模式(authorization code)
- 簡化模式(implicit)
- 密碼模式(resource owner password credentials)
- 客戶端模式(client credentials)
(1)授權碼模式(authorization code)
功能最完整、流程最嚴密的授權模式。它的特點就是通過客戶端的后台服務器,與"服務提供商"的認證服務器進行互動。
(2)簡化模式(implicit grant type)
不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了"授權碼"這個步驟,因此得名。所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證。
(3)密碼模式(Resource Owner Password Credentials Grant)
用戶向客戶端提供自己的用戶名和密碼。客戶端使用這些信息,向"服務商提供商"索要授權。在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這通常用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統的一部分,或者由一個著名公司出品。而認證服務器只有在其他授權模式無法執行的情況下,才能考慮使用這種模式。
(4)客戶端模式(Client Credentials Grant)
指客戶端以自己的名義,而不是以用戶的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式並不屬於OAuth框架所要解決的問題。在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務提供商"提供服務,其實不存在授權問題。
注:web資源:其實就是接口。
二、授權碼模式
---以使用微博賬號登錄簡書為示例詳細講解其工作原理
1、原理概要
新浪微博作為服務提供商,擁有用戶的頭像、昵稱、郵箱、好友以及所有的微博內容,簡書希望獲取用戶存儲在微博的頭像和昵稱,假設它們是三個人:
- 簡書問新浪微博:我想要獲取用戶 A 的頭像和昵稱,請你提供
- 微博說:我需要經過用戶A 本人的許可,然后去問用戶 A 是否要授權簡書訪問自己的頭像和昵稱
- 用戶 A 對微博說:我給簡書一個臨時的鑰匙,如果他給你出示了這把鑰匙,你就把我的資料給他
- 簡書使用戶給它的鑰匙獲取用戶頭像和昵稱信息。
以上是 OAuth 認證的大概流程。在使用微博授權之前,簡書需要先在微博開放平台上注冊應用,填寫自己的名稱、logo、用途等信息,微博開放平台頒發給簡書一個應用 ID 和叫 APP Secret 的密鑰,在實際對接中,會使用到這兩個參數。
- 新浪微博開放平台即是認證服務器
- 用戶發放code(時間極短)
認證服務器發放 token(時間長) - 資源服務器提供用戶資源
2、詳細流程
接下來分步詳細解釋上圖中每步都做了什么:
1.用戶點擊簡書上的微博登錄按鈕,跳轉到微博授權頁面。微博登錄按鈕的鏈接形如下方的 URL:
https://api.weibo.com/oauth2/authorize?client_id=123050457758183&redirect_uri=http://jianshu.com/callback
URL 中要包含以下參數:
- client_id:在微博開放平台申請的應用 ID
- redirect_uri:授權成功后要跳轉到的地址
點擊以上鏈接后跳轉到微博的授權頁面如下圖:
這個頁面會告訴用戶第三方應用要獲取用戶的哪些數據,以及擁有什么權限,比如在上圖中簡書會要求獲得個人信息、好友關系、分享內容到微博以及獲得評論的權限,用戶點擊“允許”則表示允許簡書獲得這些數據,進行下一步。
2.頁面自動跳轉到初始參數中redirect_uri
定義的那個URL,並自動在 URL 末尾添加一個 code
參數,實際跳轉的地址形如:
http://jianshu.com/callback?code=2559200ecd7ea433f067a2cf67d6ce6c
3.第三步,簡書通過上一步獲取的 code 參數換取 Token,Token 就是前文中說到的鑰匙。簡書請求如下的接口獲取 Token:
POST https://api.weibo.com/oauth2/access_token
要包含以下參數:
- client_id:在微博開放平台申請的應用 ID
- client_secret:在微博開放平台申請時提供的APP Secret
- grant_type:需要填寫authorization_code
- code:上一步獲得的 code
- redirect_uri:回調地址,需要與注冊應用里的回調地址以及第一步的 redirect_uri 參數一致
{ "access_token": "ACCESS_TOKEN",//Token 的值 "expires_in": 1234,//過期時間 "uid":"12341234"//當前授權用戶的UID。 }
5.在第四步中獲取了access_token ,使用它,就可以去獲取用戶的資源了,要獲取用戶昵稱和頭像,請求如下接口:
GET https://api.weibo.com/2/users/show.json
攜帶參數:
- access_token:上一步獲取的access_token
- uid:用戶的賬號 id,上一步的接口有返回
- 重新授權登錄
- 使用refresh_token,重新申請。(一般用在不間斷連續在線)
總結:
目前很多互聯網公司都提供了自己的開放平台使第三方應用接入。開源項目中也有很多框架提供了OAuth的實現,例如Spring Security OAuth,Apache Oltu等。使用OAuth協議能夠很好的保證第三方應用訪問用戶數據的安全性。
參考文獻:
https://www.jianshu.com/p/0db71eb445c8
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html