登錄和認證是什麼?都是在鑑別用戶的身份。如何鑑定識別出這是哪一個用戶?或者說,有什麼方式只有用戶本身知道(夠安全),又能說出這是他本身?因而就有了"用戶名+密碼"、"用戶名+手機號" 的方式出現。下面主要分析 「用戶名+密碼」的登錄鑑權方式:安全
那麼咱們如何作到能夠不用提供用戶名和密碼呢?咱們在用戶登陸的時候,根據用戶的身份信息去生成一種能標記用戶的 token。服務器
有了認證信息 token 之後,新的問題就是如何保證這個 token 是安全的呢?若是其餘人拿到了這個 token 就能僞造用戶身份了。解決方案就是鑑定這個 token 是否是用戶本人在使用,通常咱們經過如下方式,若是咱們能保證下面的兩種驗證信息是一直都沒變或者在可接受的範圍內,咱們就能認爲這個用戶一直在使用咱們下發的 token。微信
如今咱們已經作到了 token + (位置、設備信息)來鑑定用戶的身份。若是咱們每次請求都要鑑定這些信息來確認用戶身份,勢必影響咱們服務的性能。那麼如何減小這樣的斷定呢?session
第一種方式不建議,服務器維護每一個用戶定時複雜,隨機可能會有大量用戶同時鑑定的性能問題。那麼就是第二種了,客戶端定時請求一次鑑定,服務端須要強制客戶端定時請求一次鑑定,而這個定時時間就是一個安全因素,若是在期間 token 泄露就會形成用戶信息安全問題,時間不能太長,也不能過短,參考微信的是 7200s 就是 2 小時。架構
那麼如何強制客戶端每隔一段時間作一次驗證呢?很簡單,咱們給 token 設個有效時間,到失效時間客戶端就必須請求一次新的 token,因而就有了 refresh token。性能
用戶登陸後,每次請求服務時客戶端請求都要包含鑑權信息,服務端根據鑑權信息查詢用戶信息和其合法性。目前鑑權信息能夠有以下方式:加密
在登錄完成後,服務端將返回做爲認證鑑權的隨機不重複 token,客戶端每次請求帶上這個 token(通常放在請求的 header 裏面)。服務端經過 token 查詢到 token 對應的用戶信息。lua
登錄完成後,服務端根據用戶信息和其餘安全因素加密生成一個安全令牌(也就是 JWTS,JSON Web Tokens),該令牌中包含了用戶的身份信息,在認證鑑權時只需驗證令牌的合法性便可,解密便可取到用戶信息。blog
鑑權方式 | 優勢 | 不足 |
---|---|---|
集中式 session 方式 | 1. 服務端維護用戶狀態,能夠管理用戶狀態,沒有失效和用戶信息一致問題; 2. 安全性相對較高 | 1. 服務端維護 Session 狀態,根據 Token 獲取用戶信息須要極高的性能要求 |
令牌方式 | 1. 客戶端記錄用戶狀態,服務是無狀態的,沒有集中式的性能問題。 2. 業務解耦,鑑權邏輯相對簡單的多,令牌方式在技術實現性能和可靠性上也相對容易些 | 1. 令牌強制失效或者續簽問題,令牌強制失效或更新須要額外工做(好比封禁用戶) 2. 當用戶信息更新後,令牌裏的用戶的同步問題 |
集中式Session鑑權驗證用戶身份有以下的實現方式:token
實現 | 說明 | 優勢 | 缺點 |
---|---|---|---|
RPC調用 | 網關經過RPC調用鑑權服務,經過token獲取用戶信息 | 架構邏輯簡單,不須要額外工做 | 增長響應 RT |
Redis 直讀 | 網關直接讀取鑑權服務的 Redis,驗證並獲取用戶信息 | 高性能 | 須要網關也集成鑑權驗證邏輯,而且維護 Redis 的配置 |
Nginx Lua | 在 Nginx 裏經過 lua 腳本實現鑑權邏輯 | 性能最好 | 1. 在網關以前,對簽名無效的請求也須要作鑑權驗證。 2. Nginx 改造,lua 開發成本 |
令牌方式鑑權的實現就簡單的多, 網關直接解析 JWT 信息獲取用戶信息,而後帶着用戶信息去請求業務數據。