首頁>科技>

一 面臨問題

當前移動app最常見的保持登入的方案就是:持續重新整理的JWT(json web token)方案。

即使用者登入後,客戶端獲得JWT,此後不斷重新整理或是過期後重新整理token。

這個方案使用得十分廣泛,幾乎成了事實標準。但並不安全,有以下幾個問題:

1,JWT 金鑰管理問題

JWT 的安全的基石是保證祕鑰(secret key)的安全,因為一旦祕鑰洩露,擁有祕鑰的人可以偽造所有使用者。這給管理帶來了麻煩,我們還要完全信任管理人員,管理人員變動就要修改祕鑰,而修改祕鑰又會打斷使用者的登入狀態。也許有人會說,這不是問題,這個和資料庫賬號密碼管理一樣啊,這個還有些不同,生產環境的資料庫賬號密碼通常會有登入IP限制。

2,JWT 無法登出的問題

當用戶修改密碼後,通常需要登出之前頒發的token,為了實現這個功能需要引入token的集中儲存和檢查,這破壞了JWT分散式的優點。

3,JWT 的重新整理機制有問題。

為了安全,很多人都知道token長期保持不變不安全,通常會採取重新整理token的機制。當是當下,很多重新整理機制是為了重新整理而重新整理,常見的token重新整理機制是:到期後重新整理,或是提前重新整理,或者定時重新整理。如果token被盜,黑客和合法使用者都可以通過重新整理來獲取新的token,這並沒帶來實際的安全提升。

二 問題解答

1,針對JWT祕鑰管理問題

這裡給出的方案就是不使用JWT, 採用一個類似session 的機制,使用一個隨機值(uuid)做token, 使用者資料在後臺集中的redis儲存和查詢。暫且稱之為UUID Redis Token.

JWT的最大有點就是自身可儲存使用者資料,不用到集中的儲存點查詢,便於分散式應用,這個特點導致了已釋出的JWT無法撤銷。現實中,很多使用JWT的公司並不是單純的在jwt裡取使用者資料,依舊在集中的伺服器取資料。還有,對於像圖片,視訊等需要使用者登入的檢查,通常把token放到url 裡,而JWT顯得資料過大。

使用redis在後端儲存使用者資訊有良好的擴充套件性,足夠應滿足大型網站的需求。

這個的uuid 並不要求按標準格式,只需不重複即可,對於PHP 很容易生成:

$token = bin2hex(random_bytes(20));

不要嫌這一行程式碼過於簡單,對於地球上的公司,這已經足夠安全了。

講到這裡,這個機制和傳統的session 機制是類似的,uuid 相當於session-id,不同的地方是傳統session客戶端一定時間(通常為20分鐘)不活躍就自動退出,我們需要做些改進,滿足手機APP長期登陸的需求。

2,改進方案(UUID Redis Token)的特點

為了表述方便,以下假設手機APP要求90天內保持登陸,token超過2小時就重新整理
每個token有一個較長的有效期,比如90天,這個是為了滿足長期登入的需求;每個token有一個較短的重新整理間隔,比如2個小時。常常更換token 提升安全性;每當token重新整理時,建立並頒發新的token,同時修改舊的token的有效期,比如60秒後過期,保證舊的token快速到期同時又短暫可用,(併發請求時,可能會用到舊token)每當使用者重新登入或是修改密碼,刪除token。重新整理token時,利用redis或mysql 的鎖機制,確保併發請求時只有個請求刷到新的token。伺服器token處理邏輯:通過token在redis裡獲取使用者資料,如果找不到則表示token失效或錯誤,要求使用者再次登入。如果找到使用者資訊且token 是2個小時內建立的,則不重新整理token, 如果token建立時間超過2個小時前,則建立新的token給使用者,伺服器複製使用者資料到新的token,同時修改舊token 60秒後過期。

此方案,多數情況下只是對redis的讀寫操作,效能極高,在重新整理token時,需要用到redis或MySQL的鎖機制防止併發重新整理,確保同一客戶端一次重新整理只有一個請求刷到新的token,由於重新整理token操作間隔的時間較長,不是高頻操作,對效能也影響不大,配合redis叢集,足夠應對海量使用者。

  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 蘋果系統迎來最嚴格新規,安卓使用者始終沒有,果粉揚眉吐氣