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和頒發時間驗證黑名單都是我今天無意間想到的。如果你閱讀了本文有什麼不明白或者你認為有改進的地方,或者更好的地方,歡迎在評論與我交流。本文的問題,有很多人問過我,也討論了不少,我相信很多人在使用ids4是可能會有這樣的問題,所以在此發表了我的一個觀點,希望能給你參考,後續的文章我會根據這個想法來實現。
相關文章
- token 的生成雜談
- 淺談Redis安全策略佑葉Redis
- JWT TokenJWT
- SpringBoot 整合 JWT 實現 token 驗證,token 登出Spring BootJWT
- koa2,koa-jwt中token驗證實戰詳解JWT
- 淺談 Angular 專案實戰Angular
- 談談戰雙的戰鬥機制設計趨同
- 談談資料戰略的重要性
- ASP.NET Core 實戰:基於 Jwt Token 的許可權控制全揭露ASP.NETJWT
- JWT(Json WEB Token)JWTJSONWeb
- jwt生成token和token解析基礎JWT
- 談談ACT手遊戰鬥系統
- 談談 Promise 以及實現 Fetch 的思路Promise
- jwt生成token報錯JWT
- 實現基於JWT的Token登入驗證功能JWT
- 細談 vue - 抽象元件實戰篇Vue抽象元件
- 談談制定資料戰略的7個關鍵要素
- 談談如何建立價值驅動的資料戰略
- 淺談SAML, OAuth, OpenID和SSO, JWT和SessionOAuthJWTSession
- 談談fork/join實現原理
- JWT+SpringBoot實戰JWTSpring Boot
- 談談資料的貨幣化及相關戰略制定
- 基於 JWT + Refresh Token 的使用者認證實踐JWT
- 轉載:Kubernetes實戰——談談微博應對春晚等突發峰值流量的經驗
- JSON Web Token(JWT) 簡介JSONWebJWT
- token 會話設計 (JWT)會話JWT
- Spring Boot中使用token:jwtSpring BootJWT
- 談談保護敏感資料的最佳實踐
- 深入談談String.intern()在JVM的實現JVM
- 談談將資料作為戰略資產管理
- springboot+jwt做api的token認證Spring BootJWTAPI
- 談談最近的思考
- Session、Cookie、Token 【淺談三者之間的那點事】SessionCookie
- 談談SSO單點登入的設計實現
- 談談實現瀑布流佈局的幾種思路
- 頂級實用乾貨——談談Java中的volatileJava
- 談談Hadoop MapReduce和Spark MR實現HadoopSpark
- 來談談限流-從概念到實現