上一篇我們講解了 JWT 的基本原理和結構 你了解JWT嗎?,接下來我們具體實戰一下!
1. 引入依賴
<!--引入jwt--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
2. 編寫工具類
@Slf4j public class JwtUtils { private static final String SIGN = "!Q@WXDjksWE$"; /** * 生成 Token header.payload.signature */ public static String getToken(Map<String, String> map) { // 指定令牌的過期時間為 7 天 Calendar instance = Calendar.getInstance(); instance.add(Calendar.DATE, 7); // 創建 Jwt builder JWTCreator.Builder builder = JWT.create(); // 循環添加 payload map.forEach((k, v) -> builder.withClaim(k, v)); // 指定過期時間 簽名 指定加密算法和密鑰 String token = builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SIGN)); log.info("token = {}", token); return token; } /** * 1)驗證 Token 合法性【簽名一樣,token合法,過期校驗】 * 2)如果 Token 校驗過程中出現錯誤,直接拋異常 * - SignatureVerificationException: 簽名不一致異常 * - TokenExpiredException: 令牌過期異常 * - AlgorithmMismatchException: 算法不匹配異常 * - InvalidClaimException: 失效的payload異常 */ public static void verify(String token) { JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token); } /** * 獲取 token 中信息【先校驗 token 合法性,然后再拿 token 中信息】 */ public static DecodedJWT getTokenInfo(String token) { DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token); return verify; } }
3. 測試用例
@SpringBootTest @Slf4j public class TestJwt { @Test public void testJwt() { /** * JWT 中 header 默認就是 {"alg": "HS256", "typ": "JWT"} 一般不做改變 */ HashMap<String, Object> map = new HashMap<>(); // 指定令牌的過期時間為 20s Calendar instance = Calendar.getInstance(); instance.add(Calendar.SECOND, 1000); // 獲取令牌 String token = JWT.create() .withHeader(map) .withClaim("userId", 21) // payload .withClaim("username", "zhangsan") // payload .withExpiresAt(instance.getTime()) // 指定令牌的過期時間 .sign(Algorithm.HMAC256("!Q@WXDjksWE$")); // 簽名,指定加密算法和密鑰 log.info("token = {}", token); } @Test public void testValid() { // 創建驗證對象 JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("!Q@WXDjksWE$")).build(); // 校驗,獲取校驗后的結果對象信息【需要將上一個 test 執行的 token 字符串傳入,進行校驗】 DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDMzMzU3NzUsInVzZXJJZCI6MjEsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.
bLzXG8-QpcwmQSEBEtkoZVBySG2XO5I462fFwTN8MLQ"); log.info("header = {}", verify.getHeader()); log.info("userId = {}, usernmae = {}", verify.getClaims().get("userId").asInt(), verify.getClaims().get("username").asString()); log.info("過期時間 = {}", verify.getExpiresAt()); } }
4. 執行結果
5. 總結
1)JWT (Json Web Token) 令牌格式:【token = head.payload.signature】
2)校驗Token順序:a. 校驗簽名算法是否一樣; b. 校驗簽名是否一樣【即:head patload secret 是否一樣】;c. 校驗Token是否有效【前后是否一致 equals】;d. 校驗Token是否過期。