通俗化講解JWT鑑權的使用場景及結構安全
阿新 • • 發佈:2019-12-02
一、基於Session的應用開發的缺陷
在我們傳統的B\S應用開發方式中,都是使用session進行狀態管理的,比如說:儲存登入、使用者、許可權等狀態資訊。這種方式的原理大致如下:
- 使用者登陸之後,將狀態資訊儲存到session裡面。服務端自動維護sessionid,即將sessionid寫入cookie。
- cookie隨著HTTP響應,被自動儲存到瀏覽器端。
- 當用戶再次傳送HTTP請求,sessionid隨著cookies被帶回伺服器端
- 伺服器端根據sessionid,可以找回該使用者之前儲存在session裡面的資料。
當然,這整個過程中,cookies和sessionid都是服務端和瀏覽器端自動維護的。所以從編碼層面是感知不到的,程式設計師只能感知到session資料的存取。但是,這種方式在有些情況下,是不適用的。
- 比如:非瀏覽器的客戶端、手機移動端等等,因為他們沒有瀏覽器自動維護cookies的功能。
- 比如:分散式應用,同一個應用部署甲、乙、丙三個主機上,實現負載均衡應用,其中一個掛掉了其他的還能負載工作。要知道session是儲存在伺服器記憶體裡面的,三個主機一定是不同的記憶體。那麼你登入的時候訪問甲,而獲取介面資料的時候訪問乙,就無法保證session的唯一性和共享性。
當然以上的這些情況我們都有方案(如redis共享session等),可以繼續使用session來儲存狀態。但是還有另外一種做法就是不用session了,即開發一個無狀態的應用,JWT就是這樣的一種方案。
二、JWT是什麼?
筆者不想用比較高大上的名詞解釋JWT(JSON web tokens),你可以認為JWT是一個加密後的介面訪問密碼,並且該密碼裡面包含使用者名稱資訊。這樣既可以知道你是誰?又可以知道你是否可以訪問應用?
- 首先,客戶端需要向服務端申請JWT令牌,這個過程通常是登入功能。即:由使用者名稱和密碼換取JWT令牌。
- 當你訪問系統其他的介面時,在HTTP的header中攜帶JWT令牌。header的名稱可以自定義,前後端對應上即可。
- 服務端解籤驗證JWT中的使用者標識,根據使用者標識從資料庫中載入訪問許可權、使用者資訊等狀態資訊。
這就是JWT,以及JWT在應用服務開發中的使用方法。
三、JWT結構分析
下圖是我用線上的JWT解碼工具,解碼時候的截圖。注意我這裡用的是解碼,不是解密。
從圖中,我們可以看到JWT分為三個部分:
- Header,這個部分通常是用來說明JWT使用的演算法資訊
- payload,這個部分通常用於攜帶一些自定義的狀態附加資訊(重要的是使用者標識)。但是注意這部分是可以明文解碼的,所以注意是使用者標識,而不應該是使用者名稱或者其他使用者資訊。
- signature,這部分是對前兩部分資料的簽名,防止前兩部分資料被篡改。這裡需要指定一個金鑰secret,進行簽名和解籤。
四、JWT安全麼?
很多的朋友看到上面的這個解碼檔案,就會生出一個疑問?你都把JWT給解析了,而且JWT又這麼的被大家廣泛熟知,它還安全麼?我用一個簡單的道理說明一下:
- JWT就像是一把鑰匙,用來開你家裡的鎖。使用者把鑰匙一旦丟了,家自然是不安全的。其實和使用session管理狀態是一樣的,一旦網路或瀏覽器被劫持了,肯定不安全。
- signature通常被叫做簽名,而不是密碼。比如:天王蓋地虎是簽名,寶塔鎮河妖就被用來解籤。字你全都認識,但是暗號只有知道的人才對得上。當然JWT中的暗號secret不會設計的像詩詞一樣簡單。
- JWT服務端也儲存了一把鑰匙,就是暗號secret。用來資料的簽名和解籤,secret一旦丟失,所有使用者都是不安全的。所以對於IT人員,更重要的是保護secret的安全。
如何加強JWT的安全性?
- 避免網路劫持,因為使用HTTP的header傳遞JWT,所以使用HTTPS傳輸更加安全。這樣在網路層面避免了JWT的洩露。
- secret是存放在伺服器端的,所以只要應用伺服器不被攻破,理論上JWT是安全的。因此要保證伺服器的安全。
- 那麼有沒有JWT加密演算法被攻破的可能?當然有。但是對於JWT常用的演算法要想攻破,目前已知的方法只能是暴力破解,白話說就是"試密碼"。所以要定期更換secret並且保正secret的複雜度,等破解結果出來了,你的secret已經換了。
話說回來,如果你的伺服器、或者你團隊的內部人員出現漏洞,同樣沒有一種協議和演算法是安全的。
期待您的關注
- 向您推薦博主的系列文件:《手摸手教您學習SpringBoot系列-16章97節》
- 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。