01.15 JWT Token 刷新和作廢

之前一篇文章簡單介紹了下JWT的用法,涉及到token的簽發和驗證。有人說JWT不適合用於替換傳統的 session+cookies 機制用於Web應用的用戶登錄狀態維護,很大原因就是這塊問題。

雖然之前的案例裡面,我們可以成功在登錄後獲取一個Token,然後訪問服務器的時候帶著這個Token,服務器就可以知道當前訪問的用戶Uid了,假設現在有一下需求:

  • 登錄後7天不用重複登錄
  • 超過30天沒有訪問網站則需重新登錄,否則一直有效
  • 修改密碼功能
JWT Token 刷新和作廢

Token續簽問題

對於第一個問題,我們可以在jwt的 Payload 裡面設置一個過期時間,比如說7天,超過這個時間Token無效。但是如果只是簡單的這麼做的話就會帶來另一個問題: 假如一個用戶正在訪問網站,突然Token失效了,用戶就會掉登錄,體驗太差。

所以,大部分時候我們都是採用第二種策略: 超過xx天不訪問網站則需要重新登錄,如果中間連續訪問網站的話則不要重新登錄,對於很多手機App,我們可不希望用戶天天輸賬號密碼登錄,但如果永久有效可能會帶來一些安全問題。

這其實就是Token的續簽問題,我們看一下網上提到的一些解決方案:

1.更新Payload裡面的過期時間。

JWT的Payload裡面可以設置一個過期時間,我們可以在用戶每次訪問的時候把這個過期時間更新一下。由於JWT的secret加密機制,只要exp變了,整個Token就變了,所以這種機制相當於每次重新頒發了一個新的Token。

這種方案簡單粗暴,存在性能問題,還有安全問題,以前的那麼多Token咋辦?

2.快過期的時候更新Token

比如說離過期時間還有不到1個小時的時候才更新Token,性能上面可能好一點,但是如果一個用戶一直在訪問,但是恰好最後一個1個小時內沒有訪問網站,那豈不是也gg了?

3.使用Cache記錄Token過期時間

Token本身不設置過期時間,然後我們在redis或memcached等緩存裡面單獨設置一個有效期,每次訪問的時候刷新過期時間。

其實這個方案和使用session機制無異,session也可以保存在redis或者memcached裡面的。所以,有人戲說這是重新發明了session 。。。

4.使用refreshToken

借鑑 oauth2 的設計,返回給客戶端一個 refreshToken,允許客戶端主動刷新JWT。一般而言,jwt 的過期時間可以設置為數小時,而 refreshToken 的過期時間設置為數天。 我對oauth2不太熟悉,不過很明顯這個方案更加複雜了,而且為什麼不拿舊的Token去刷新JWT呢?

5.推薦方案

最後說一下我覺得比較合適的方案,當服務器接受到一個Token後,如果它已經過期,但是已過期的時間在xx天內,比如說30天,我們就返回一個新的Token。比如說Token的有效期是7天,但是如果過期時間不超過30天就可以用舊的Token換取一個新的Token,如果超過了30天那就需要重新登錄。

Token作廢問題

當用戶退出登錄、修改密碼之後,講道理我們是需要作廢之前的Token,比如說用戶的Token被盜用了,只能通過修改密碼來防止賬號被盜用。如果使用session機制就很簡單了,我們清空服務器session,或者使用新的session替換之前舊的session也行。

由於Token是無狀態的,理論上只要不過期就可以一直用,你說這咋辦?為了安全,必須得做一些額外的工作!

1.Cache

如果你之前是採用把Token存在cache裡面這種方案,那麼你只要刪除cache裡面的key就可以了。不過如果你真的是採用這種方案,還不如直接用session,這時候的Token和sessionid沒區別。

2.用戶關聯

有人說,建一張表把uid和Token關聯起來,這樣一個用戶只有一個有效的Token,或者存cache也行,建立uid和Token的一對一關係,這方案和1差不多。無論是存表還存cache,每次訪問都必不可免的需要訪問庫或cache。

3.黑名單

在數據表或cache裡面維護一個黑名單,也避免不了查庫或者查cache,為了避免這個庫內容過多,可以定期清理數據庫,或者給cache設置一個有效期。比如說在上面說的例子裡面,有效期應該設置為30天,30天之後就不用管了。

其實我比較喜歡第3種方案,第2種方案如果用戶多了對庫壓力大,而第3種,除非用戶經常修改密碼或者退出登錄,不然這個數據集不會很大。

如果不考慮安全,我們完全可以不考慮Token作廢問題,那麼我們就必須在防止XSS攻擊上面做好工作,比如說使用https,cookies設置httpOnly。。。

是否需要使用JWT Token?

看完之後大家是否發現原來JWT Token並沒有那麼好用,這也是很多人說的不要採用JWT的原因了: 講真,別再使用JWT了!、請停止使用 JWT 認證 。。。

仔細看完這些文章其實大家會發現JWT尤其適合那些一次性驗證的應用,比如說有些網站的文件下載為了防止盜鏈,會在url後面追加一些字符串,這些字符串其實就是Token,它裡面可能包含了用戶信息和過期時間,你發送給別人下載或者想盜鏈就非常麻煩了。

至於用不用我覺得還是看需求,你覺得呢?


分享到:


相關文章: