2016-08-28 55 views
1

據我所知,JWT刷新令牌的典型(和簡化的)用法如下:如何使用JWT刷新令牌和短期訪問令牌不是大規模不安全?

  1. 用戶登錄到系統。用戶被授予刷新令牌和短暫(例如:10分鐘到期)的訪問令牌。刷新令牌存儲在「驗證服務器」的數據庫中以用於撤銷目的。任何對應用程序(「資源服務器」)的請求都將使用短期訪問令牌。
  2. 當用戶10分鐘啓動時,客戶端將使用刷新令牌向auth服務器發送新訪問令牌的請求。
  3. 當用戶更改其密碼或取消特定登錄的訪問權限(如遇盜竊,丟失設備等),刷新令牌將從auth服務器數據庫中刪除並呈現無效狀態。

因此,當用戶意外泄漏密碼或丟失設備時,他可以簡單地更改自己的密碼,這將導致所有先前發出的刷新令牌失效。

但是,這裏顯而易見的安全漏洞是短期訪問令牌在接下來的10分鐘內仍然完全有效。而10分鐘,無論多麼短的時間,仍然有足夠的時間讓惡意用戶造成一些損害。

唯一可能的解決方案,我能想到的是:

  • 保持訪問令牌的黑名單白名單或。這使得刷新令牌的使用看起來非常多餘。如果我們打算在每個請求上點擊數據庫 或保留一個黑名單 訪問令牌的緩存列表,那麼刷新令牌有什麼意義?

  • 使訪問令牌的期滿更短(例如:每1分鐘而不是每10分鐘)。這並不能解決問題,它只是做了一些傷害控制,因爲它縮短了惡意用戶不得不造成傷害的時間窗口。每分鐘打一個新的 訪問令牌的數據庫似乎並不比在每個請求上打 數據庫好得多。

回答

1

我一直在研究完全相同的問題。雖然我不能說我對這個問題有任何權威性,但我很高興通過大量的研究和建立概念證明來分享我的想法。

要求是有即時令牌訪問令牌撤銷。在應用程序的正常運行期間,惡意用戶訪問某人帳戶的實際可能性相對較低。這並不是說它不應該被考慮在內,但對於進入系統的請求的99.9%並不是這種情況,因此它不會檢查訪問令牌對數據庫的所有請求在我看來,問題是糟糕的設計。

然而,不好的設計與否,它並沒有改變要求。要求訪問令牌每分鐘刷新一次似乎不會更好,因爲它會給auth服務器和數據庫帶來巨大的壓力。管理內存訪問令牌撤銷列表不會有太大好處,因爲它不會在實例間共享。取決於你的用戶數量,這可能能夠在使用數據庫的同時獲得一種方式,但我認爲它不會超出某個特定點。

我選擇的解決方案是使用共享內存數據庫/緩存。我評估過Cassandra,Redis和Apache Ignite,暫時決定使用Ignite。因爲我不確定一旦這些產品投入生產將如何執行,所以我已經將這些組件輕鬆地換成另一種內存解決方案,以防性能不足。

我有一個JWT過濾器負責驗證每個請求,最後我調用共享緩存來檢查訪問令牌撤銷列表。我預計絕大多數時候這份清單將是空白的。爲了進一步減少潛在的性能下降,我使用MD5將令牌散列爲大約40個字符,然後撤銷它們。此功能使我可以擁有長達一小時的訪問令牌生命和擁有18小時使用壽命的刷新令牌,而無需擔心如果出現需要,我將無法移除惡意用戶。

就我個人而言,我沒有看到在後端跟蹤某些用戶狀態的方法。訣竅是這樣做,您仍然可以輕鬆添加後端的實例來擴展您的應用程序。

+0

對不起,對於遲到的回覆,但如果我理解這個權利,你基本上會在所有需要訪問它的應用程序服務器上覆制內存數據庫/緩存。我從來沒有真正使用像Redis這樣的內存數據庫,但是我會猜測他們能夠輕鬆地在不同的自身實例之間進行同步。 – aetheus

+0

Redis和其他內存提供者與我習慣的編程範例不同。每個實例都知道如何相互通信,但它們需要進行配置才能完成。這就是說,他們得到了很好的支持,並且我認爲不難想出。大多數圖書館都會向你展示如何與他們互動。 Redis至少有幾個關於如何保護他們在生產中的教程。 – blur0224

2

智威湯遜代幣的目的是它們是獨立的,並在短時間內獨立生活。如果這不符合您的要求,您可以恢復到另一種類型的訪問令牌,即在授權服務器(AS)上需要所謂的自省的不透明訪問令牌。你是對的(如果這個調用的結果沒有被緩存),那個調用每次都會觸發AS,部分地挫敗刷新令牌的用途,但另一方面,主動必須撤銷每個資源服務器的緩存訪問令牌結果那已經做了內省電話會導致管理和頭頂上的噩夢。

沒有銀彈。您必須選擇訪問令牌類型,到期時間和緩存持續時間,以符合您的情況和最佳安全要求。