在会话中使用JWT
在黑客新聞,reddit和博客上,該主題已經討論了很多次。 共識是–請勿使用JWT(用于用戶會話)。
而且我在很大程度上同意對JWT的典型論點 , 典型的“但我可以使其工作……”的解釋以及JWT標準的缺陷的批評 。 。
我不會在這里重復所有內容,因此請閱讀這些文章。 您真的可以使用JWT付諸實踐,了解它很復雜,并且對于大多數用例來說幾乎沒有好處。 我猜對于API調用是有意義的,特別是如果您在單頁應用程序中為RESTful客戶端重用相同的API,那么我將重點討論用戶會話用例。
受到所有這些批評之后,我違背了以上文章的建議,使用了JWT,瀏覽了他們的論點并聲稱我處于最佳狀態。 我很可能是錯的。
我將用戶ID存儲在作為cookie存儲的JWT令牌中。 不是本地存儲,因為這是有問題的。 不是整個狀態,因為我不需要那可能導致問題(在鏈接的文章中指出)。
我想避免在設置中跨節點共享會話。 這是不使用Web服務器/框架的會話機制的非常令人信服的原因。 不,您不需要擁有數百萬個用戶即可要求您的應用程序在多個節點上運行。 實際上,它應該幾乎總是在(至少)兩個節點上運行,因為節點會死掉并且您不希望停機。 負載平衡器上的粘性會話是解決該問題的一種方法,但是您只是將集中式會話存儲外包給了負載平衡器(有些負載平衡器可能不支持它)。 共享的會話緩存(例如memcached,elasticache,hazelcast)也是一種選擇,許多Web服務器(至少在Java中)支持可插入的會話復制機制,但是這為體系結構引入了另一個組件,要支持的堆棧的另一部分以及可能會破裂。 它不一定很壞,但是如果有一種簡單的方法可以避免它,那我就去做。
為了避免共享會話存儲,您需要在請求/響應周期中傳遞整個會話狀態(作為cookie,請求參數,標頭),或者需要接收userId并從數據庫或緩存中加載用戶。 據我們了解,前者可能是一個錯誤的選擇。 盡管有諸如ASP.NET和JSF之類的框架將整個狀態轉儲到頁面HTML中的事實,但這聽起來并不好。
至于后者–您可能會說:“好吧,如果您打算在每個請求中從數據庫中加載用戶,這將會很慢,并且如果您使用緩存,那么為什么不對會話本身使用緩存呢?” 。 好吧,緩存可以是本地的。 記住,我們只有幾個應用程序節點。 每個節點可以為當前活動的用戶提供一個本地內存緩存。 所有節點都將加載相同的用戶(在負載均衡器以循環方式將一些請求路由到它們之后)的事實并不重要,因為該緩存很小。 但是您不必在節點之間復制它,也不必照顧從群集來來回去的新節點,處理節點之間的網絡問題,等等。每個應用程序節點都是孤島應用程序節點。
因此,這里是我對鏈接文章的第一個反對意見–僅將用戶標識符存儲在JWT令牌中并不是沒有意義的,因為它可以使您免于會話復制。
對JWT標準及其加密的安全性的批評又如何呢? 完全正確,很容易用腳射擊。 這就是為什么我僅將JWT與MAC一起使用,并且僅將其與接收令牌時經過驗證的特定算法一起使用,從而(有選擇地)避免了所有陷阱。 公平地說,我愿意使用其中一篇文章中提出的替代方案PASETO ,但是它沒有Java庫,實現它需要花費一些時間(將來可能會這樣做)。 總結一下–如果存在另一種易于使用的經過身份驗證的cookie加密方法,我會使用它。
因此,我基本上是在“ PASETO模式”下使用JWT,它只有一種操作和一種算法。 作為一般方法,這應該很好-本文沒有批評在令牌(和無狀態應用程序節點)中包含用戶標識符的想法,而是批評了標準的復雜性和脆弱性。 這是我的第二個反對意見–“不使用JWT”被廣泛理解為“不使用令牌”,而事實并非如此。
我在為簡化體系結構和缺乏共享狀態而努力時是否引入了一些漏洞? 我希望不是。
翻譯自: https://www.javacodegeeks.com/2018/03/using-jwt-sessions.html
總結
- 上一篇: 怎么把照片变成油画风格?PS照片处理技巧
- 下一篇: 星际争霸2电脑单机版(星际争霸2电脑单机