一 面臨問題
當(dāng)前移動app最常見的保持登錄的方案就是:持續(xù)刷新的JWT(json web token)方案雅任。
即用戶登錄后,客戶端獲得JWT花枫,此后不斷刷新或是過去后刷新黍瞧。
這個方案有兩個問題:
1,JWT 自身的問題椎例。
JWT 的安全的基石是保證秘鑰(secret key)的安全挨决,因為一旦秘鑰泄露,擁有秘鑰的人可以偽造所有用戶订歪。這給管理帶來了麻煩脖祈,我們還要完全信任管理人員,管理人員變動就要修改秘鑰刷晋,而修改秘鑰又會打斷用戶的登錄狀態(tài)盖高。也許有人會說,這不是問題眼虱,這個和數(shù)據(jù)庫賬號密碼管理一樣啊喻奥,這個還有些不同,生產(chǎn)環(huán)境的數(shù)據(jù)庫賬號密碼通常會有登錄IP限制捏悬。
2撞蚕,JWT 的刷新機制有問題。
為了安全过牙,很多人都知道token長期保持不變不安全甥厦,通常會采取刷新token的機制。當(dāng)是當(dāng)下寇钉,很多刷新機制是為了刷新而刷新刀疙,常見的刷新機制是:token到期后或是提前刷新,或者就是定時刷新扫倡。如果token被盜谦秧,黑客和合法用戶都可以通過刷新來獲取新的token,這并沒帶來實際的安全提升镊辕。
二 問題解答
1油够,針對JWT秘鑰管理問題
這里給出的方案就是不使用JWT, 采用一個類似session 的機制,使用一個隨機值(uuid)做token, 數(shù)據(jù)到后臺集中的redis存儲查詢征懈。暫且稱之為UUID Redis Token.
JWT的最大有點就是自身和存儲用戶數(shù)據(jù)石咬,不用到集中的存儲點查詢,便于分布式應(yīng)用卖哎,這個特點導(dǎo)致了已發(fā)布的JWT不易撤銷」碛疲現(xiàn)實中删性,很多使用JWT的公司并不是單純的在jwt里取用戶數(shù)據(jù),依舊在服務(wù)器取數(shù)據(jù)焕窝。還有蹬挺,對于像圖片,視頻等需要用戶登錄的檢查它掂,通常把token放到url 里巴帮,而JWT顯得數(shù)據(jù)過大。
使用redis在后端保存用戶信息有良好的擴展性虐秋,足夠應(yīng)滿足大型網(wǎng)站的需求榕茧。
講到這里,這個機制和傳統(tǒng)的session 機制是一樣的客给,uuid 相當(dāng)于session-id.
這個的uuid 并不要求按標(biāo)準(zhǔn)格式用押,只需不重復(fù)即可,對于PHP 很容易生成
$token = bin2hex(random_bytes(20));
2 UUID Redis Token的特點和刷新機制
- 每個token有一個較長的有效期,比如90天靶剑,這個是為了滿足長期登錄的需求
- 每個token有一個較短的刷新間隔蜻拨,比如2個小時。常常更換token 提升安全性
- 每當(dāng)token刷新時桩引,創(chuàng)建新的token缎讼,同時修改舊的token的有效期,比如60秒后過期阐污,保證舊的token短暫可用休涤,(并發(fā)請求時咱圆,可能會用到舊token)
- 每當(dāng)用戶重新登錄或是修改密碼笛辟,刪除token。
- 利用redis或mysql 的鎖機制序苏,確保并發(fā)請求時只有個刷到新的token手幢。
服務(wù)器token處理邏輯:通過token在redis里獲取用戶數(shù)據(jù),如果找不到則表示token失效或錯誤忱详,要求用戶再次登錄围来。如果找到用戶信息且token 是2個小時內(nèi)創(chuàng)建的,則不刷新token, 如果token創(chuàng)建時間超過2個小時前匈睁,則創(chuàng)建新的token給用戶监透,服務(wù)器復(fù)制用戶數(shù)據(jù)到新的token,同時修改舊token 60秒后過期航唆。