什么是OAuth2
OAuth(Open Authorization,開放授權)是為用戶資源的授權定義了一個安全、開放及簡單的標准,第三方無需知道用戶的賬號及密碼,就可獲取到用戶的授權信息
OAuth2.0是OAuth協議的延續版本,但不向后兼容OAuth 1.0即完全廢止了OAuth1.0
應用場景
第三方應用授權登錄:在APP或者網頁接入一些第三方應用時,時常會需要用戶登錄另一個合作平台,比如QQ,微博,微信的授權登錄,第三方應用通過oauth2方式獲取用戶信息
運作流程
微信開發文檔流程說明如下:
1. 第三方發起微信授權登錄請求,微信用戶允許授權第三方應用后,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數;
2. 通過code參數加上AppID和AppSecret等,通過API換取access_token;
3. 通過access_token進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操作。
這里給出我們項目的QQ及微信登錄的相關Oauth2示意圖。
下面來分別講解其中的幾個點
第三方引導用戶跳轉至認證服務器的授權頁面
在引導跳轉的時候需要攜帶如下的幾個參數
- response_type:授權類型。授權碼模式下,就固定為code
- app_id:第三方應用的標識id。
- redirect_uri:重定向uri,也就是在授權成功后認證服務器讓用戶重定向的地址。一般而言也就是當前用戶在第三方應用中最初的請求地址
- scope:授權范圍。可選內容,可以根據第三方應用和實現方的要求自行制定合適的值。
- state:透明的驗證參數。RFC6749文檔推薦認證服務器在重定向的時候應該原封不同的返還這個參數。注意,該參數嚴格來說應該是一個必須參數。用來防止CSRF攻擊。也就是說用於讓第三方服務器驗證重定向回來的uri的確是認證服務器的行為而不是其他的攻擊者偽造的。一般來說跳轉到認證服務器的授權頁面是走的https,但是認證服務器重定向到回調地址的時候可能走的就是http。此時code存在泄漏以及url存在被偽造的風險。那么第三方應用必須要有辦法驗證該回調是否的確由認證服務器發起,並且的確是之前自己的授權請求導致的回調。做法其實也不復雜,就是在session中保存一個隨機值,作為state參數。認證服務器回調的時候帶上該state參數,第三方應用驗證該參數是否與自己session中的state參數值一致即可。如果認證的授權頁面不是https加密的,那么在發出請求的時候,認證state參數可能會被竊取。那么這個時候還有另外一種做法。也就是第三方應用發送的是加密后的state參數,而認證服務器重定向的時候攜帶的是解密后的state參數。第三方應用只要在session中判斷解密后的值是否與session的一致,也可以達到防止攻擊的目的。這樣,授權頁面也就是可以走在普通的http之中了。
用戶選擇是否給予授權
這一步是一個用戶行為。目前基本的做法都是讓用戶在授權頁面上輸入用戶名和密碼。為了保證安全性,這個頁面需要由https來進行保護。當然,如果有其他的方式來保證用戶名密碼,以及認證的state參數不會泄露也是可以的。如果用戶輸入正確的用戶名和密碼,一般就確認為用戶給予授權。
認證服務器生成code並且讓用戶重定向至指定的url
如果用戶給予授權,則認證服務器需要生成一個唯一的授權碼code。該code的時效性應該比較短,在5分鍾以內比較合適。並且該code只能使用一次,下次就會失效。同時,該code與客戶端的id,redirect-uri參數是一一對應的關系。認證服務器此時應該讓用戶重定向至一開始指定的redirect_uri。攜帶上state和code參數
第三方應用使用code到認證服務器處兌換令牌access token
第三方應用在驗證過state參數的正確性后,接着就可以使用code到認證服務器處換取token。這一步,第三方應用需要攜帶上的參數有
- code:就是認證服務器給予的code參數
- appid:客戶端的唯一標識
- redirect_uri:也就是第一步請求中的重定向參數。因為code實際上是與appid和redirect_uri一一對應的。所以用code換取令牌的時候也要攜帶上這兩個參數
- grant_type: 授權模式,這里固定為"authorization_code"
- appkey:用於驗證應用的身份。appid和appkey可以理解為應用自己的用戶名和密碼。
oauth2的服務器本身都是走https。所以都可以直接明文傳輸不需要考慮安全性問題。不過如果不是http的,也可以直接參數用戶名密碼登錄的方式,就是給appkey進行md5運算。 關於為何不直接傳遞accesstoken的問題,是基於安全考慮。因為認證服務器是基於Https,而第三方應用可以是http的。如果在回調的時候直接帶上accesstoken,就存在着泄露的問題。
認證服務器返回accesstoken
認證服務器在驗證過參數的合法性后,生成一個全局唯一的token,並且返回給第三方應用。返回的內容采用json表示,返回的參數主要有
- access_token: 用於獲取對應資源的令牌
- expires_time: 該令牌的有效期
- reflesh_token: 用戶獲取新的accesstoekn的token。由於accesstoken的有效期比較短,一旦失效,用戶需要再走上面的流程是比較繁瑣的。為了提升用戶體驗,可以使用reflesh_token來獲取新的accesstoken。不過這個做法,已經有不同的實現方將這個返回參數去掉了。因為實際上reflesh_token也就意味着accesstoekn是永久有效的了。那和直接延長accesstoken的有效期也沒有直接區別了。
accesstoken換取對應的用戶信息
到這基本用戶的信息我們就可以拿到了,OAuth2廣泛用於第三方登錄以及資源控制。大家也可以學習和借鑒