登陸鑑權方案設計

JMCui發表於2019-06-05

一、概述

 登陸和認證是什麼?都是在鑑別使用者的身份。如何鑑定識別出這是哪個使用者?或者說,有什麼方式只有使用者自己知道(夠安全),又能說出這是他自己?於是就有了"使用者名稱+密碼"、"使用者名稱+手機號" 的方式出現。下面主要分析 “使用者名稱+密碼”的登陸鑑權方式:

  1. 出於安全考慮,我們不可能在所有的請求裡都使用“使用者名稱+密碼”。
  2. "使用者名稱+密碼"不能儲存在任何地方,最安全的方式就是存放在使用者自己的腦子裡,也就是說如果要使用 “使用者名稱+密碼” 就得讓使用者自己提供。

 那麼我們如何做到可以不用提供使用者名稱和密碼呢?我們在使用者登入的時候,根據使用者的身份資訊去生成一種能標記使用者的 token。

 有了認證資訊 token 以後,新的問題就是如何保證這個 token 是安全的呢?如果其他人拿到了這個 token 就能偽造使用者身份了。解決方案就是鑑定這個 token 是不是使用者本人在使用,一般我們通過以下方式,如果我們能保證下面的兩種驗證資訊是一直都沒變或者在可接受的範圍內,我們就能認為這個使用者一直在使用我們下發的 token。

  1. 位置資訊(ip、經緯度)
  2. 裝置資訊

 現在我們已經做到了 token + (位置、裝置資訊)來鑑定使用者的身份。如果我們每次請求都要鑑定這些資訊來確認使用者身份,勢必影響我們服務的效能。那麼如何減少這樣的判定呢?

  1. 服務端隨機或者定時選定一次請求鑑定
  2. 客戶端定時請求一次鑑定

第一種方式不建議,伺服器維護每個使用者定時複雜,隨機可能會有大量使用者同時鑑定的效能問題。那麼就是第二種了,客戶端定時請求一次鑑定,服務端需要強制客戶端定時請求一次鑑定,而這個定時時間就是一個安全因素,如果在期間 token 洩露就會造成使用者資訊保安問題,時間不能太長,也不能太短,參考微信的是 7200s 就是 2 小時。

 那麼如何強制客戶端每隔一段時間做一次驗證呢?很簡單,我們給 token 設個有效時間,到失效時間客戶端就必須請求一次新的 token,於是就有了 refresh token。

二、鑑權方式

 使用者登入後,每次請求服務時客戶端請求都要包含鑑權資訊,服務端根據鑑權資訊查詢使用者資訊和其合法性。目前鑑權資訊可以有如下方式:

1. 集中式 session 方式

 在登陸完成後,服務端將返回作為認證鑑權的隨機不重複 token,客戶端每次請求帶上這個 token(一般放在請求的 header 裡面)。服務端通過 token 查詢到 token 對應的使用者資訊。

2. 令牌方式

 登陸完成後,服務端根據使用者資訊和其他安全因素加密生成一個安全令牌(也就是 JWTS,JSON Web Tokens),該令牌中包含了使用者的身份資訊,在認證鑑權時只需驗證令牌的合法性即可,解密即可取到使用者資訊。

3. 比較

鑑權方式 優點 不足
集中式 session 方式 1. 服務端維護使用者狀態,可以管理使用者狀態,沒有失效和使用者資訊一致問題;

2. 安全性相對較高
1. 服務端維護 Session 狀態,根據 Token 獲取使用者資訊需要極高的效能要求
令牌方式 1. 客戶端記錄使用者狀態,服務是無狀態的,沒有集中式的效能問題。

2. 業務解耦,鑑權邏輯相對簡單的多,令牌方式在技術實現效能和可靠性上也相對容易些
1. 令牌強制失效或者續簽問題,令牌強制失效或更新需要額外工作(比如封禁使用者)

2. 當使用者資訊更新後,令牌裡的使用者的同步問題

三、鑑權實現方案

1. 集中式 session 方式流程時序

登陸鑑權方案設計

  1. 客戶端在未登入的狀態下請求業務服務,在閘道器沒有獲取到認證資訊時直接返回 401,告知客戶端需要登入。
  2. 客戶端使用“手機號+密碼”、“手機號+驗證碼”的方式請求登陸服務。
  3. 閘道器發現是登陸服務後,請求登陸認證服務。
  4. 登陸認證服務通過手機號碼查詢使用者資訊,同時生成 token。
  5. 返回閘道器 token,閘道器將 token 返回給客戶端。
  6. 客戶端帶著 token 請求閘道器,閘道器將 token 傳給鑑權服務,鑑權服務通過 token 查詢使用者資訊並返回給閘道器,閘道器將使用者資訊轉給業務服務,完成接下來的業務流程。

2. 令牌方式流程時序

登陸鑑權方案設計

  1. 客戶端在未登入的狀態下請求業務服務,在閘道器沒有獲取到認證資訊時直接返回 401,告知客戶端需要登入。
  2. 客戶端使用“手機號+密碼”、“手機號+驗證碼”的方式請求登陸服務。
  3. 閘道器發現是登陸服務後,請求登陸認證服務,同時生成 token(JWT資訊),並將 token 返回給客戶端。
  4. 客戶端帶著 token 請求閘道器,閘道器根據 token(JWT資訊)解密得到使用者資訊,並將使用者資訊轉給業務服務,完成接下來的業務流程。

四、鑑權技術方案

1. 集中式Session鑑權技術方案

集中式Session鑑權驗證使用者身份有如下的實現方式:

實現 說明 優點 缺點
RPC呼叫 閘道器通過RPC呼叫鑑權服務,通過token獲取使用者資訊 架構邏輯簡單,不需要額外工作 增加響應 RT
Redis 直讀 閘道器直接讀取鑑權服務的 Redis,驗證並獲取使用者資訊 高效能 需要閘道器也整合鑑權驗證邏輯,並且維護 Redis 的配置
Nginx Lua 在 Nginx 裡通過 lua 指令碼實現鑑權邏輯 效能最好 1. 在閘道器之前,對簽名無效的請求也需要做鑑權驗證。

2. Nginx 改造,lua 開發成本

2. 令牌方式鑑權技術方案

令牌方式鑑權的實現就簡單的多, 閘道器直接解析 JWT 資訊獲取使用者資訊,然後帶著使用者資訊去請求業務資料。

相關文章