您好,登錄后才能下訂單哦!
本篇文章為大家展示了SpringBootSecurity中JWT的使用方法,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
前面簡單介紹了把默認的頁面登錄改為前后端分離的接口異步登錄的方法,可以幫我們實現基本的前后端分離登錄功能。但是這種基本的登錄和前面的頁面登錄還有一個一樣的地方,就是使用session和cookie來維護登錄狀態,這種方法的問題在于,擴展性不好。單機當然沒有問題,如果是服務器集群,或者是跨域的服務導向架構,就要求 session 數據共享,每臺服務器都能夠讀取 session。
一種解決方案是 session 數據持久化,寫入redis或別的持久層。各種服務收到請求后,都向持久層請求數據。這種方案的優點是架構清晰,缺點是工程量比較大。另外,持久層萬一掛了,就會單點失敗。
另一種方案是服務器索性不保存 session 數據了,所有數據都保存在客戶端,每次請求都發回服務器。JWT 就是這種方案的一個代表。關于JWT的理論知識,建議參考 阮一峰 大神寫的教程 :JSON Web Token 入門教程,這是我認為可能是寫的最清晰的一個,下面的jwt的實現也是根據此教程來實現。
具體的理論知識可以參考教程,這里簡單說下流程,用戶登錄成功后,在header中返回用戶一個token信息,這個信息里面包含了加密的用戶信息和數字簽名,最重要的還有過期時間,客戶端接到后,每次訪問接口header中都帶著這個token,服務端驗證成功后就表示處于登錄狀態,過期后再從新獲取即可。
具體的token內容包含了頭部(加密信息),載體(用戶信息),簽名(簽名兩個部分的前面)三大塊,三大塊之間用英文句號(也就是 ".")連接起來,組成一個完整的token信息
根據前面的理論知識,我們來設計一下如何使用jwt。首先我們使用jwt,就可以不再使用session和cookie,所以第一步就是:
在security配置文件中配置session為無狀態。
然后考慮構建jwt消息體,有三個部分,第一個部分就是頭部,內容是加密類型:
上面代碼中,alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ屬性表示這個令牌(token)的類型(type),JWT 令牌統一寫為JWT,最后,將上面的 JSON 對象使用 Base64URL 算法轉成字符串,作為第一部分。所以第二步就是:
在security配置文件中配置session為無狀態。
確定header信息格式
下一步確定第二部分,消息載體(Payload),這也是一個json對象,用來存放實際需要傳遞的數據。JWT 規定了7個官方字段,供選用:
當然除了這些還可以加一些其它內容,比如用戶信息,這個 JSON 對象也要使用 Base64URL 算法轉成字符串,所以第三步和第四步就是:
在security配置文件中配置session為無狀態。
確定header信息格式
確定消息體
使用 HMAC SHA256 算法 對header和消息體進行簽名作為第三部分
現在token的消息基本組合完成了,用戶登錄成功和客戶端訪問接口,都要把token放在header里面,名字是 Authorization 。所以最后一步就是,客戶端正常訪問非登錄等接口時,驗證token的合法性,所以,總體設計流程如下:
在security配置文件中配置session為無狀態。
確定header信息格式
確定消息體
使用 HMAC SHA256 算法 對header和消息體進行簽名作為第三部分
添加過濾器,驗證token合法性
上面的流程設計完了,下面我們按照流程修改項目,首先修改security配置類:
配置完后,啟動項目,訪問登錄,登錄成功后可以看到,沒有任何cookie保存下來。
首先來定義幾個常量:
然后定義Base64URL 算法編碼和解碼方法:
然后定義HmacSHA256 加密算法和獲取簽名的方法:
最后來設計一個簡單驗證token的方法:
這樣jwt工具類就設計好了,目前這幾個方法足夠操作token內容。
下面來定義jwt的內容,其實內容很簡單,就三個部分,因此,定義三個字段即可:
來看一下構造方法,
這個構造方法很便捷,使用它創建對象以后,jwt的三個部分基本都完成了,header部分和payload部分都編碼了,簽名也完成了,因此下面重寫toString方法直接可以生成token:
從這里可以看出,token整體默認是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。因此不要把密碼等重要信息放入token。
用戶登錄成功后,不再把session發給用戶,而是把jwt發送給用戶,因此修改登錄成功處理器如下:
注意上面手動把用戶的密碼信息設置為null。這里為了方便,直接使用fastjson組合對象。
帶著token訪問接口的時候,需要把token轉回登錄用戶對象,因此我們的用戶實體類和token中帶的字段名字一致,來修改一下,先看角色實體類:
再看用戶實體類:
可以看到,基本的原則就是修改的名字和父類的必要字段名字一致就行,這也是建議的字段名字。
我們把security的session改為無狀態后,雖然不再傳遞session,但是security的過濾器并沒有失效,因此造成的效果就是登錄成功后,訪問接口顯示未登錄。現在我們使用token就要在登錄前加一個驗證token的過濾器,驗證通過后直接把信息放到SecurityContextHolder中。這樣每次登錄靠驗證token來判斷是否登錄,不再靠session。來看這個過濾器:
這個過濾器很簡單,繼承了 GenericFilterBean 類,直接獲取token,判斷token不為空,驗證token,并從token的payload中取出用戶信息,放入SecurityContextHolder中,驗證失敗或者token過期直接返回token錯誤。邏輯很簡單。
最后在security類中,把這個過濾器配置到前面:
這樣我們自定義的jwt流程就完成了。可以在postman中測試一下,首先是登錄:
登錄成功后,可以看到header中放著token的信息,然后使用token放入另一個接口的header中訪問接口,可以看到訪問成功:
有興趣的可以debug跟蹤一下流程。
(1)JWT 默認是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。
(2)JWT 不加密的情況下,不能將秘密數據寫入 JWT。
(3)JWT 不僅可以用于認證,也可以用于交換信息。有效使用 JWT,可以降低服務器查詢數據庫的次數。
(4)JWT 的最大缺點是,由于服務器不保存 session 狀態,因此無法在使用過程中廢止某個 token,或者更改 token 的權限。也就是說,一旦 JWT 簽發了,在到期之前就會始終有效,除非服務器部署額外的邏輯。
(5)JWT 本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有權限。為了減少盜用,JWT 的有效期應該設置得比較短。對于一些比較重要的權限,使用時應該再次對用戶進行認證。
(6)為了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。
上述內容就是SpringBootSecurity中JWT的使用方法,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。