Java如何簡單快速入門JWT(token生成與驗證)
一、Token簡單介紹
簡單來說,token就是一個將信息加密之后的密文,而jwt也是token的實現(xiàn)方式之一,用于服務(wù)器端進(jìn)行身份驗證和授權(quán)訪問控制。由于是快速入門,這里簡單介紹一下jwt的生成原理
jwt由三部分組成。分別是
1.Header(標(biāo)頭),一般用于指明token的類型和加密算法
2.PayLoad(載荷),存儲token有效時間及各種自定義信息,如用戶名,id、發(fā)行者等
3.Signature(簽名),是用標(biāo)頭提到的算法對前兩部分進(jìn)行加密,在簽名認(rèn)證時,防止止信息被修改
而Header和PayLoad最初都是json格式的鍵值對,格式如下
Header:
{
"alg": "HS256", #簽名加密所用的算法
"typ": "JWT" #表名token的格式
}PayLoad:此段json中保存了用戶的部分信息
{
"sub": "1234567890", #主題
"name": "John Doe", #用戶名
"isVIP": true, #是否為vip用戶
"exp": 1677740800 #過期時間
}Signature:簽名,首先將Header和PayLoad的json字符串進(jìn)行Base64Url加密后,得到兩個加密后的字符串,然后把這兩個字符串由‘.’拼接起來,然后再將拼接好的字符串再用之前 Header中提到的算法與一個密鑰(一般為一個字符串)進(jìn)行加密后得到一個新的字符串,最后把這個新字符串和之前使用Base64Url加密后的兩段字符串進(jìn)行連接,最終得到token字符串,然后就可以把它發(fā)送給客戶端進(jìn)行存儲了。
一般jwt格式token格式如下
eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiam9rZXIiLCJleHAiOjE2OTQxODE2NDUsInB3ZCI6IjEyMyJ9.vDrOQp-FkmRCQBzfaZsxzkef-iNjkAuAaqvT7Ns5Ab0 #(Header).(PayLoad).(Signature)
當(dāng)然,作為快速上手jwt的文章,這里就不對jwt及token進(jìn)行更加深入的講解了,以上內(nèi)容只需要做簡單了解有個映像即可,總而言之:
token就是一個在服務(wù)器端生成,包含了部分用戶信息,最后發(fā)送給客戶端進(jìn)行保管的加密字符串,當(dāng)客戶端向服務(wù)器再次發(fā)起請求時,請求需攜帶token,服務(wù)器端對token進(jìn)行驗證,以確定用戶是否有權(quán)訪問。(以此來實現(xiàn),登錄驗證,權(quán)限校驗,記住密碼等功能)
接下來做一個簡單的代碼實現(xiàn)
二、代碼實現(xiàn)
- 導(dǎo)入相關(guān)依賴jar包(此jwt框架功能比較齊全且簡單,適合初學(xué)者)
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>- jwt生成
首先需要一個字符串密鑰進(jìn)行加密,這個字符串可自定義,然后提前規(guī)劃好你項目的jwt想要儲存哪些自定義信息,例如用戶名,密碼,id,等等(這里為了方便演示,這里就把用戶名以及密鑰字符串設(shè)為常量了)
package com.example.jwtdemo.Controller;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
@Controller("/")
public class TestController {
//用戶的用戶名
private static final String USERNAME = "admin";
//用于簽名加密的密鑰,為一個字符串(需嚴(yán)格保密)
private static final String KEY = "the_key";
@GetMapping("/jwt")
public String setToken() {
//獲取jwt生成器
JWTCreator.Builder jwtBuilder = JWT.create();
//由于該生成器設(shè)置Header的參數(shù)為一個<String, Object>的Map,
//所以我們提前準(zhǔn)備好
Map<String, Object> headers = new HashMap<>();
headers.put("typ", "jwt"); //設(shè)置token的type為jwt
headers.put("alg", "hs256"); //表明加密的算法為HS256
//開始生成token
//我們將之前準(zhǔn)備好的header設(shè)置進(jìn)去
String token = jwtBuilder.withHeader(headers)
//接下來為設(shè)置PayLoad,Claim中的鍵值對可自定義
//設(shè)置用戶名
.withClaim("username", USERNAME)
//是否為VIP用戶
.withClaim("isVIP", true)
//設(shè)置用戶id
.withClaim("userId", 123)
//token失效時間,這里為一天后失效
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24))
//設(shè)置該jwt的發(fā)行時間,一般為當(dāng)前系統(tǒng)時間
.withIssuedAt(new Date(System.currentTimeMillis()))
//token的發(fā)行者(可自定義)
.withIssuer("issuer")
//進(jìn)行簽名,選擇加密算法,以一個字符串密鑰為參數(shù)
.sign(Algorithm.HMAC256(KEY));
//token生成完畢,可以發(fā)送給客戶端了,前端可以使用
//localStorage.setItem("your_token", token)進(jìn)行存儲,在
//下次請求時攜帶發(fā)送給服務(wù)器端進(jìn)行驗證
System.out.println(token);
return token;
}
}
最終生成的jwt
eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJleHAiOjE2OTQyNzA0OTMsImlhdCI6MTY5NDE4NDA5MywiaXNWSVAiOnRydWUsInVzZXJuYW1lIjoiYWRtaW4ifQ.JiTMn2jDaUTolPXB0TCBBOwSHG1l75W2oy2isdWhQIU
PS:以上代碼中向jwt中注冊的鍵值對不是都為必須的,需按照自己的情況進(jìn)行設(shè)置
- jwt驗證
我們從客戶端的請求中獲取其攜帶的token進(jìn)行驗證,已確定其是否有權(quán)訪問或進(jìn)行其他的業(yè)務(wù)邏輯操作
@GetMapping("/verify")
public boolean verify(HttpServletRequest request) {
/*從請求頭中獲取token(具體要看你的token放在了請求的哪里,
這里以放在請求頭舉例)
*/
String token = request.getHeader("token");
/*判斷token是否存在,若不存在,驗證失敗,
并進(jìn)行驗證失敗的邏輯操作(例如跳轉(zhuǎn)到登錄界面,
或拒絕訪問等等)*/
if (token == null) return false;
/*獲取jwt的驗證器對象,傳入的算法參數(shù)以及密鑰字符串(KEY)必須
和加密時的相同*/
var require = JWT.require(Algorithm.HMAC256(KEY)).build();
DecodedJWT decode;
try {
/*開始進(jìn)行驗證,該函數(shù)會驗證此token是否遭到修改,
以及是否過期,驗證成功會生成一個解碼對象
,如果token遭到修改或已過期就會
拋出異常,我們用try-catch抓一下*/
decode = require.verify(token);
} catch (Exception e) {
//拋出異常,驗證失敗
return false;
}
//若驗證成功,就可獲取其攜帶的信息進(jìn)行其他操作
//可以一次性獲取所有的自定義參數(shù),返回Map集合
Map<String, Claim> claims = decode.getClaims();
if (claims == null) return false;
claims.forEach((k, v) -> System.out.println(k + " " + v.asString()));
//也可以根據(jù)自定義參數(shù)的鍵值來獲取
if (!decode.getClaim("isVIP").asBoolean()) return false;
System.out.println(decode.getClaim("username").asString());
//獲取發(fā)送者,沒有設(shè)置則為空
System.out.println(decode.getIssuer());
//獲取過期時間
System.out.println(decode.getExpiresAt());
//獲取主題,沒有設(shè)置則為空
System.out.println(decode.getSubject());
return true;
}總結(jié)
到此這篇關(guān)于Java如何簡單快速入門JWT(token生成與驗證)的文章就介紹到這了,更多相關(guān)JWT token生成與驗證 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Swagger文檔自動生成PDF/HTML/Word解決方案詳細(xì)指南
本指南詳細(xì)介紹了Swagger?YAML/JSON定義、Swagger?UI的使用、Swagger轉(zhuǎn)為Markdown格式以及Markdown轉(zhuǎn)為PDF/HTML/Word的過程,包括工具如Pandoc的運(yùn)用,并提供了一個Spring?Boot應(yīng)用集成Swagger2和Swagger2Markup的示例,闡述了API文檔的生成流程,感興趣的朋友一起看看吧2025-08-08
使用Spirng Boot Admin監(jiān)控Spring Cloud應(yīng)用項目
這篇文章主要介紹了使用Spirng Boot Admin監(jiān)控Spring Cloud應(yīng)用項目,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
Java代理模式之靜態(tài)代理與動態(tài)代理的區(qū)別及優(yōu)缺點
代理模式是一種常用的設(shè)計模式,它允許通過引入一個代理對象來控制對目標(biāo)對象的訪問,在Java中,代理模式被廣泛應(yīng)用,它可以提供額外的功能,如權(quán)限檢查、緩存、日志記錄等,本文將介紹靜態(tài)代理與動態(tài)代理的區(qū)別及優(yōu)缺點,需要的朋友可以參考下2023-06-06
idea創(chuàng)建javaweb原生項目的實現(xiàn)示例
這篇文章主要介紹了idea創(chuàng)建javaweb原生項目的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
如何在SpringBoot+Freemarker中獲取項目根目錄
這篇文章主要介紹了如何在SpringBoot+Freemarker中獲取項目根目錄的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10

