1. 程式人生 > >一口氣說出 OAuth2.0 的四種鑑權方式,面試官會高看一眼

一口氣說出 OAuth2.0 的四種鑑權方式,面試官會高看一眼

>本文收錄在個人部落格:[www.chengxy-nds.top](http://www.chengxy-nds.top),技術資源共享,一起進步 上週我的自研開源專案開始破土動工了,[《開源專案邁出第一步,10 選 1?頁面模板成了第一個絆腳石 》](https://mp.weixin.qq.com/s/vFHpxh3sry1p-Yj0Q7ZwJQ) ,密謀很久才付諸行動,做這個的初衷就是不想讓自己太安穩,**技術這條路不進步就等於後退**,必須要逼著自己學習。 專案偏向於技術實踐,因此不會做太多的業務堆砌,業務程式碼還是在公司學習比較好。現在正在做技術的選型與儲備,像比較主流的,`專案前後端分離`、`微服務`、`Springboot`、`Springcloud` 等都會應用到專案中,其實很多技術我也不會,也是在反覆的查閱資料求證,探索的過程技術提升真的要比工作中快很多,畢竟主動與被動學習是有本質區別的。 這幾天打算先把專案的前後端分離架構搭建完成,既然是前後端分離專案就免不了做鑑權, 所以 `oauth2.0` 是一個我們不得不瞭解的知識點。 --- ## 一、OAuth2.0 為何物 `OAuth` 簡單理解就是一種授權機制,它是在客戶端和資源所有者之間的授權層,用來分離兩種不同的角色。在資源所有者同意並向客戶端頒發令牌後,客戶端攜帶令牌可以訪問資源所有者的資源。 `OAuth2.0` 是`OAuth` 協議的一個版本,有`2.0`版本那就有`1.0`版本,有意思的是`OAuth2.0` 卻不向下相容`OAuth1.0` ,相當於廢棄了`1.0`版本。 **舉個小栗子解釋一下什麼是 OAuth 授權?** 在家肝文章餓了定了一個外賣,外賣小哥30秒火速到達了我家樓下,奈何有門禁進不來,可以輸入密碼進入,但出於安全的考慮我並不想告訴他密碼。 此時外賣小哥看到門禁有一個高階按鈕“`一鍵獲取授權`”,只要我這邊同意,他會獲取到一個有效期 2小時的令牌(`token`)正常出入。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200706163230102.png#pic_center) 令牌(`token`)和 `密碼` 的作用雖然相似都可以進入系統,但還有點不同。`token` 擁有許可權範圍,有時效性的,到期自動失效,而且無效修改。 ## 二、OAuth2.0 授權方式 `OAuth2.0` 的授權簡單理解其實就是獲取令牌(`token`)的過程,`OAuth` 協議定義了四種獲得令牌的授權方式(`authorization grant` )如下: - 授權碼(`authorization-code`) - 隱藏式(`implicit`) - 密碼式(`password`): - 客戶端憑證(`client credentials`) 但值得注意的是,不管我們使用哪一種授權方式,在三方應用申請令牌之前,都必須在系統中去申請身份唯一標識:客戶端 ID(`client ID`)和 客戶端金鑰(`client secret`)。這樣做可以保證 `token` 不被惡意使用。 下面我們會分析每種授權方式的原理,在進入正題前,先了解 `OAuth2.0` 授權過程中幾個重要的引數: - `response_type`:code 表示要求返回授權碼,token 表示直接返回令牌 - `client_id`:客戶端身份標識 - `client_secret`:客戶端金鑰 - `redirect_uri`:重定向地址 - `scope`:表示授權的範圍,`read`只讀許可權,`all`讀寫許可權 - `grant_type`:表示授權的方式,`AUTHORIZATION_CODE`(授權碼)、`password`(密碼)、`client_credentials`(憑證式)、`refresh_token` 更新令牌 - `state`:應用程式傳遞的一個隨機數,用來防止`CSRF`攻擊。 #### 1、授權碼 `OAuth2.0`四種授權中授權碼方式是最為複雜,但也是安全係數最高的,比較常用的一種方式。這種方式適用於兼具前後端的`Web`專案,因為有些專案只有後端或只有前端,並不適用授權碼模式。 下圖我們以用`WX`登入掘金為例,詳細看一下授權碼方式的整體流程。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200706172813832.png#pic_center) 使用者選擇`WX`登入掘金,掘金會向`WX`發起授權請求,接下來 `WX `詢問使用者是否同意授權(常見的彈窗授權)。`response_type` 為 `code` 要求返回授權碼,`scope` 引數表示本次授權範圍為只讀許可權,`redirect_uri` 重定向地址。 ```javascript https://wx.com/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=http://juejin.im/callback& scope=read ``` 使用者同意授權後,`WX` 根據 `redirect_uri`重定向並帶上授權碼。 ```javascript http://juejin.im/callback?code=AUTHORIZATION_CODE ``` 當掘金拿到授權碼(code)時,帶授權碼和密匙等引數向`WX`申請令牌。`grant_type`表示本次授權為授權碼方式 `authorization_code` ,獲取令牌要帶上客戶端密匙 `client_secret`,和上一步得到的授權碼 `code`。 ```javascript https://wx.com/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=http://juejin.im/callback ``` 最後 `WX` 收到請求後向 `redirect_uri` 地址傳送 `JSON` 資料,其中的`access_token` 就是令牌。 ```javascript { "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", ...... } ``` ### 2、隱藏式 上邊提到有一些`Web`應用是沒有後端的, 屬於純前端應用,無法用上邊的授權碼模式。令牌的申請與儲存都需要在前端完成,跳過了授權碼這一步。 前端應用直接獲取 `token`,`response_type` 設定為 `token`,要求直接返回令牌,跳過授權碼,`WX`授權通過後重定向到指定 `redirect_uri` 。 ```javascript https://wx.com/oauth/authorize? response_type=token& client_id=CLIENT_ID& redirect_uri=http://juejin.im/callback& scope=read ``` ### 3、密碼式 密碼模式比較好理解,使用者在掘金直接輸入自己的`WX`使用者名稱和密碼,掘金拿著資訊直接去`WX`申請令牌,請求響應的 `JSON`結果中返回 `token`。`grant_type` 為 `password` 表示密碼式授權。 ```javascript https://wx.com/token? grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID ``` 這種授權方式缺點是顯而易見的,非常的危險,如果採取此方式授權,該應用一定是可以高度信任的。 ### 4、憑證式 憑證式和密碼式很相似,主要適用於那些沒有前端的命令列應用,可以用最簡單的方式獲取令牌,在請求響應的 `JSON` 結果中返回 `token`。 `grant_type` 為 `client_credentials` 表示憑證式授權,`client_id` 和 `client_secret` 用來識別身份。 ```javascript https://wx.com/token? grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET ``` ## 三、令牌的使用與更新 ### 1、令牌怎麼用? 拿到令牌可以呼叫 `WX` API 請求資料了,那令牌該怎麼用呢? 每個到達`WX`的請求都必須帶上 `token`,將 `token` 放在 `http` 請求頭部的一個`Authorization`欄位裡。 如果使用`postman` 模擬請求,要在`Authorization` -> `Bearer Token` 放入 `token`,**注意**:低版本`postman` 沒有這個選項。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200707115819454.png) ### 2、令牌過期怎麼辦? `token`是有時效性的,一旦過期就需要重新獲取,但是重走一遍授權流程,不僅麻煩而且使用者體驗也不好,那如何讓更新令牌變得優雅一點呢? 一般在頒發令牌時會一次發兩個令牌,一個令牌用來請求`API`,另一個負責更新令牌 `refresh_token`。`grant_type` 為 `refresh_token` 請求為更新令牌,引數 `refresh_token` 是用於更新令牌的令牌。 ```javascript https://wx.com/oauth/token? grant_type=refresh_token& client_id=CLIENT_ID& client_secret=CLIENT_SECRET& refresh_token=REFRESH_TOKEN ``` ## 總結 `OAuth2.0` 授權其實並不是很難,只不過授權流程稍顯麻煩,邏輯有些繞,`OAuth2.0`它是面試經常會被問到的知識點,還是應該多瞭解一下。下一篇實戰 `OAuth2.0`四種授權,敬請期待,歡迎關注哦~ --- 原創不易,燃燒秀髮輸出內容,如果有一丟丟收穫,點個贊鼓勵一下吧! 整理了幾百本各類技術電子書,送給小夥伴們。關注公號回覆【666】自行領取。和一些小夥伴們建了一個技術交流群,一起探討技術、分享技術資料,旨在共同學習進步,如果感興趣就掃碼加入我們吧! ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC8yLzQvMTcwMGU0Mjk1MDQzMjQ0Yg?x-oss-process=image/form