基於jwt token機制鑒權架構


常見的鑒權方式有兩種,一種是基於session,另一種是基於token方式的鑒權,我們來淺談一下兩種 鑒權方式的區別。

兩種鑒權方式對比

session

  1. 安全性:session是基於cookie進行用戶識別的,cookie如果被截獲,用戶很容易受到跨站請求偽造的攻擊。
  2. 擴展性:session是有狀態的,是具有IP黏貼性和有中心化特性的,在分布式環境下,雖然每台服務器業務邏輯一樣,但是session是保存在各個服務器中的,而且每個服務器內存是不共享的,如果使用session去實現分布式部署的話,需要使用其他的一些技術手段去實現,比如spring session,將session保存在第三方服務中,比如redis,這樣一旦第三方服務出現問題,整個驗權系統就會奔潰,在電商系統及高並發系統中的集群化處理顯然是不合適的。
  3. 抗壓能力:通常session是存儲在內存中的,每個用戶通過認證后都會將session存儲在服務器內存中,當用戶量增大的情況下服務器的壓力也隨之增大。

token

  1. 安全性:瀏覽器會將接收到的token值存儲在Local Storage中,(通過js代碼寫入Local Storage,通過js獲取,並不會像cookie一樣自動攜帶)
  2. 擴展性:token是無狀態的,是去中心化的,在分布式環境下,各個服務器中的服務只對token進行數據查詢,它不需要在服務端保留用戶信息或者會話信息,這意味着用戶不需要考慮登錄的是哪一台服務器,高效的解決了session擴展性的弊端。
  3. 抗壓能力:token與session的不同主要在認證成功后,會對當前用戶數據進行加密,生成一個加密字符串token,返還給客戶端(服務器端並不進行保存)

基於token的鑒權方式

業界常用的授權標准有兩種,一種是使用auth2,這種方式更適合於類似第三方授權登錄,比如微信、微博、QQ信任登錄業務。另一種是oauth,即第三方無需知道用戶和密碼就可以申請獲得該資源的授權,更適用於對用戶的權限校驗並分配訪問權限,比如常見的登錄后分配可見資源(按鈕、菜單等)類型網站。

Javashop電商系統 采用的是oauth方式的鑒權標准。我們以系統的應用為例來介紹oauth的方案。

 

1. 登錄
服務端校驗密碼,成功后返回access_token和refresh_token,客戶端記錄上述token。
2. 訪問API
在訪問API之前解析access_token,並且查看是否過期,如果不過 期則請求API,如果過期,則要刷新令牌,在請求API。
3. 刷新token
攜帶有效期的refresh_token換回有效token,如果refresh_token過期,則需要用戶重新登錄。
4. 注銷
請求注銷api,服務器端和客戶端應同時刪除token的存儲。

 

1. 客戶端請求API
攜帶access_token信息,如果生成環境不會直接攜帶access_token,會使用加密后的簽名校驗。祥見以下防重放機制。
2. 獲取token
根據環境不同而有不同的獲取token方式。
3. 解析token
通過JWT工具將token解析。
4. 由redis讀取token
根據uid拼接key讀取access_token, 如果不存在這個用戶的token說明已經登出。
5. 驗證token
判斷次token是否屬於此uid,判斷token是否過期,如果過期則進行以下刷新token的流程。
6. 注入權限
如果token驗證成功,根據user信息生成權限注入到spring安全上下文中。

 

 

 

刷新token流程

 

 

 

1. 客戶端請求API
攜帶refresh_token,如果是生產環境不會直接攜帶refresh_token信息,詳見以下防重放攻擊。
2. 獲取token
根據環境不同而有不同的獲取token方式。
3. 解析token
通過JWT工具將token解析。
4. token讀取
根據uid拼接key讀取出access_token,如果不存在這個用戶的token說明用戶已經登出。
5. 驗證token
判斷此token是否屬於此uid,判斷token是否已經過期,如果過期,則返回refresh_token過期錯誤,此時用戶需要重新登錄。
6. 刷新token
如果refresh_token 驗證成功,則重新生成access_token和refresh_token,上述有效期以當前時間向后計算,替換此用戶在redis中的token,並將token返回給客戶端。

 

防重放機制

 

 

 

一、 參數的讀取
1. 在生產環境時,不能直接傳遞token,而是要傳遞簽名數據,服務器端驗簽后由Redis中獲取簽名。
2. 如果是非生產環境,直接由header中讀取token。
二、 生產環境傳遞如下參數
memberid (用戶id)
nonce(隨機字串,6位)
timestamp(當前時間戳,到秒)
sign= md5( uid+ nonce + timestamp +token )
三、 驗證邏輯
1. 驗證時間戳
判斷時間戳是否起過60s,大於60s則判別為重放攻擊。

2. 驗證nonce
首先驗證nonce在 reids中是否存在,如果存在,則判別為重放攻擊,否則將nonce記錄在redis中(key為:"nonce"+uid+"_"+nonce),失效時間為60s。
3. 驗證sign
md5( uid+ nonce + timestamp +token ) 驗證是簽名是否通過。
4. 驗證token
通過uid拿到token ,驗證邏輯同驗權流程。

 

 

當然在不同的業務場景下實現方案是多種多樣的,僅以此方案拋磚引玉,供大家參考。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM