我们真的需要JWT吗?
JWT(JSON Web Token)是目前最流行的認證方案之一。博客園、各種技術公眾號隔三差五就會推一篇JWT相關的文章,真的多如牛毛。但我對JWT有點困惑,今天寫出來跟大家探討探討,不要噴哈。
JWT原理
本文默認讀者已經對JWT有所了解,下面不再詳細介紹JWT,只簡單提一下。
JWT全稱JSON Web Token。當服務器認證成功后會生成一個Token,這個token包含了header、payload、signature三部分信息。其中payload的內容有過期時間、簽發時間、還有自定義的字段。自定義字段往往用來存放用戶信息,比如UserId,UserName等等信息。當客戶端收到這個token后存儲在Cookie,localstorage或者別的什么地方并且以后每次請求都帶上token。服務端對請求所攜帶的token進行解析,判斷是否過期是否合法。
以上簡單的描述了下JWT的工作原理,因為jwt的payload攜帶了過期時間、用戶信息等,所以JWT有別于傳統Session方案的一個最大不同就是JWT是無狀態的,JWT不用在內存或DB里維持session的狀態,直接拿到token解析就可以了。
JWT的優點
無狀態?
這個優點真的爽,因為沒有了session,不用考慮session服務器的壓力所以可以毫無顧忌的水平擴展,個人認為這是JWT最大的一個優點,也是JWT的核心內容。但是這也帶來了一個致命的問題:無法讓單獨某個用戶(token)過期或者失效,恰恰這又是一個非常非常常用的功能。
為了解決這個問題,網上提出一些方案:比如服務端設置一個blacklist或者配合redis來存儲token跟過期時間,每次請求到服務端解析JWT之后再次去blacklist或者redis里查詢一次看看是否已經注銷或者已經過期。
但是。。。這樣不就又把session請回來了嗎?這樣的方案跟我用sessionId去取session又有啥區別呢?所謂session不一定非要是asp.net mvc又或者springmvc自帶的session管理叫做session,任何帶有中心存儲功能能維持狀態的東西都是session,比如上面方案里的redis就是一個確確實實的session。
跨域?
因為傳統基于cookie的session機制sessionid存在cookie里,但是cookie不能跨域。但是JWT把token放在http的一個Authorization header上傳輸所以就可以輕松跨域。
但是sessionId就一定要存在cookie下嗎,sessionId同樣也可以存儲在localstorage里,然后請求的時候攜帶在http的某個header上,事實上cookie本身也是通過http的一個header傳輸的。這樣不就同樣可以跨域了嗎?sessionId跟token有區別嗎?個人認為沒有區別,都只是一個字符串而已。jwt怎么在客戶端存儲放在哪個header上那么sessionId就同樣可以。
數據更安全?
JWT的簽名也僅僅是仿篡改,把數據直接存儲在客戶端,盡管可以加密(JWT加密不是必須的),但是顯然談不上安全。如果是一串無意義的sessionId,它不存儲數據,又不能篡改,是不是更安全呢?
預防CSRF?
這個通跨域那個解釋一樣,sessionId不一定非要存儲在cookie中。
總結
為了預防被噴,再次強調下。今天寫下這不是為了噴JWT。JWT本身設計沒有什么問題。真正無狀態的JWT確實可以帶來實實在在的好處,服務端水平擴容變的異常容易,再也不用擔心session復制的效率問題,也不用擔心session掛掉后整個集群全部無法正常工作的問題,確實是一個實實在在的好東西。但是,好東西就一定大家都需要嗎?個人認為如果您所要開發的系統并發量不是那么高,對水平擴展沒那么高的需求,并且對用戶注銷是剛需,那么請好好考慮下是否真的需要JWT。或許簡單的sessionId配合一個存儲工具比如redis,更能符合你的要求。如果你的程序并發高,用戶量大,實時在線人多,那么使用真無狀態JWT是一個非常好的選擇。它能夠讓你從容的水平擴容,它能夠讓你省下不少session服務器的費用,session服務不再是您系統的瓶頸。但是這樣的系統又有多少?
關注公眾號一起玩轉技術吧
總結
以上是生活随笔為你收集整理的我们真的需要JWT吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CLR的简单理解
- 下一篇: 终于弄明白了 Singleton,Tra