IdentityServer4實戰 - 談談 JWT Token 的安全策略

一.前言

衆所周知,IdentityServer4 默認支持兩種類型的 Token,一種是 Reference Token,一種是 JWT Token 。前者的特點是 Token 的有效與否是由 Token 頒發服務集中化控制的,頒發的時候會持久化 Token,然後每次驗證都需要將 Token 傳遞到頒發服務進行驗證,是一種中心化的比較傳統的驗證方式。JWT Token 的特點與前者相反,每個資源服務不需要每次都要都去頒發服務進行驗證 Token 的有效性驗證,該 Token 由三部分組成,其中最後一部分包含了一個簽名,是在頒發的時候採用非對稱加密算法(最新的JWT Token)進行數據簽名的,保證了 Token 的不可篡改性,保證了安全,與頒發服務的交互,僅僅是獲取公鑰用於驗證簽名,且該公鑰獲取以後可以自己緩存,持續使用,不用再去交互獲得,除非Token包含的 keyid 對應的 公鑰沒被緩存(新的),就會再次向頒發服務獲取。我畫了一張流程圖,大家可以去查看:https://www.cnblogs.com/stulzq/p/9226059.html

這裏說一下我在文章說所說的名詞:

頒發服務:即生成Token的服務。

資源服務:提供給用戶訪問的API資源

二.JWT Token 的安全問題

前言中有過敘述,JWT 類型的 Token 在驗證的時候,無需依靠頒發服務來驗證 Token 的有效性,是一種去中心化的驗證方式,這就意味着頒發服務無法集中控制 Token。假如 Token 暴露以後,在 Token 有效期內,將會一直被人惡意使用,這時候該怎麼辦呢?這裏主要從兩個方面來講,一個是儘量避免被惡意獲取Token,一個是被惡意獲取了怎麼控制失效。請聽下面分解。

1.使用 HTTPS

此種方式是避免被人獲取惡意獲取Token。

HTTPS 在傳輸數據時,數據內容是加密的,可以有效避免中間人攻擊,所以在使用 JWT Token 的程序建議都採用HTTPS。

2.添加自定義Token失效機制

此種方式是被惡意獲取了怎麼控制失效。

因爲 IdentityServer4 對 JWT Token,默認是沒有控制失效的機制的,所以如果我們想添加這種機制,只有我們自定義,下一節做詳細介紹。

三.自定義Token失效機制

1.簡單黑名單模式

顧名思義,就是添加一個 Token 黑名單,這個黑名單建議存在諸如 Redis 等分佈式緩存,數據庫等介質,可以讓所有資源服務共同訪問。不推薦添加在資源服務本地緩存,如果這樣做,那麼每次添加黑名單還需要同步到每個資源服務。每個資源服務在每次驗證Token的時候需要查詢一下黑名單,如果在黑名單裏面,即 Token 無效。

2.進階黑名單模式

前面小節的 【簡單黑名單模式】 有一個非常大的弊端,就是每個 Token 驗證時都需要去驗證是否在黑名單,正常情況下,我們正常的Token 是佔絕大多數的,如果用此種機制,那麼對資源是一種很大的浪費。那麼我們需要設立一種機制,來讓我們認爲 可疑 的Token進行黑名單驗證,那麼如何來判斷Token是否可疑呢,我這裏想了一種方式。

如何判斷 Token 是否可疑:

我們在生成Token的時候,可以添加自定義 Claim (身份信息單元),那麼我們可以參考網站登錄的安全機制,那麼我們可以添加一個用戶ip的Claim,這樣我們生成的Token都會攜帶用戶生成Token時的IP,我們每次驗證Token是否有效時,就可以根據客戶端來源IP與Token攜帶的IP進行匹配,如果匹配不上,那麼該Token我們就可以認爲是可疑的,從而進行黑名單的驗證。

該方式相對於前面的 【簡單黑名單模式】模式算是一個比較好的進階了。

在這裏,我們還需要考慮到IP作爲用戶的私密信息,我們將IP放入Token時,需要對IP進行加密。因爲 JWT Token 前兩部分,僅僅是 base64 Encode 而已。

Claim 詳解請參考 http://www.cnblogs.com/stulzq/p/8726002.html

3.強化黑名單模式

無論是【簡單黑名單模式】還是【進階黑名單模式】,我們在對比黑名單時是對token進行完全比對,這樣的方式,在某些場景就存在侷限性,比我想讓該用戶在某某時間以前頒發的Token都算作黑名單。所以我們在判斷黑名單時可以根據用戶id以及token頒發時間來判斷。如果讓規則自動失效?我們可以用前面設定的 token頒發時間加上我們頒發服務設置的token有效時間就等於規則失效時間。

4.將Token添加進黑名單的方式

我們前面設立了黑名單模式,那麼我們的Token何時加入黑名單呢,難道讓用戶說,我的 Token 被盜了,你把我的 Token加入黑名單吧,這肯定不現實。我們可以在退出登錄時,就自動往黑名單添加一條規則,採用【強化黑名單模式】添加用戶id以及當前時間作爲token頒發時間來驗證。比如用戶id1000,此用戶在 2018-09-20 12:11 退出,我們就可以添加一條規則 userid=1000,tokenissuetime=2018-09-20 12:11 ,該規則表示只要用戶id爲1000的並且token頒發時間小於2018-09-20 12:11的token,都被算作黑名單token。

這時有人可能會說,這個token如果還是這個用戶再次拿來使用,那還是有效的,你這個怎麼沒讓他失效呢?我們設立黑名單模式就是爲了避免用戶的還在有效期的Token被他人惡意使用。對於用戶自己來說,這個問題就無關緊要了。

5.全部 Token 失效的機制。

全部Token失效的方式,目前我想了兩種:

1.更換頒發服務的密鑰對,並且重啓所有資源服務(資源服務獲取的公鑰默認存在內存,重啓可以丟失)。這樣原本的Token在驗證時,將會找不到對應的公鑰,導致驗籤失敗從而Token無效。

2.類似於前面【強化黑名單模式】的驗證黑名單的方式,我們可以在驗證Token的流程中加兩個配置,一個是控制這種配置是否開啓的開關,一個是某個時間,規則就是如果在這個時間以前頒發Token全部算作無效Token。這種就需要資源服務支持熱加載配置,從而避免重啓資源服務。

我個人推薦第二種方式。

四.寫在最後

文中所訴是總結了我長久以來的想法,token加入ip還有根據id和頒發時間驗證黑名單都是我今天無意間想到的。如果你閱讀了本文有什麼不明白或者你認爲有改進的地方,或者更好的地方,歡迎在評論與我交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章