1.JWT的介紹
知乎有一篇文章介紹的很形象 認證方式的前世今生,以及 JWT 的使用
具體和Springboot的集成使用可參考另一篇博客:SpringBoot集成JWT實現token驗證
2.使用demo
1 package com.drz.proxy.internetProxy.util; 2 3 import java.util.Date; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import org.apache.commons.codec.binary.Base64; 8 import org.apache.commons.codec.binary.StringUtils; 9 10 import com.auth0.jwt.JWT; 11 import com.auth0.jwt.JWTVerifier; 12 import com.auth0.jwt.algorithms.Algorithm; 13 import com.auth0.jwt.exceptions.JWTCreationException; 14 import com.auth0.jwt.exceptions.JWTVerificationException; 15 import com.auth0.jwt.interfaces.DecodedJWT; 16 17 /** 18 * JWT token串結構: header.payload.signature 19 * signature=HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),Secret) 20 * 21 * token保存在客戶端,每次請求傳到后端,服務端只保留密鑰,不要把密鑰放在header和payload中; 22 * 23 * header中默認傳遞參數: 24 * {"typ":"JWT","alg":"HS256"} 25 * 26 * payload官方定義包含屬性如下(非強制): 27 * iss: jwt簽發者 28 * sub: jwt所面向的用戶 29 * aud: 接收jwt的一方 30 * exp: jwt的過期時間,這個過期時間必須要大於簽發時間 31 * nbf: 定義在什么時間之前,該jwt都是不可用的. 32 * iat: jwt的簽發時間 33 * jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。 34 * payload 自定義數據:存放我們想放在token中存放的key-value值 35 */ 36 public class JWTUtil { 37 38 /** 39 * 過期時間 40 */ 41 private static final long EXPIRE_TIMEMILLS = 6000; 42 43 /** 44 * jwt 密鑰 45 */ 46 private static final String SECRET = "jwt_secret"; 47 48 public static String create() { 49 try { 50 Algorithm algorithm = Algorithm.HMAC256(SECRET); 51 52 Map<String, Object> headerMap = new HashMap<String, Object>(); 53 headerMap.put("date", "2022-01-01 18:00"); 54 headerMap.put("where", "城東小樹林"); 55 String token = JWT.create().withHeader(headerMap)//可自定義傳遞參數 56 // .withIssuer("auth0")//簽發者 57 .withIssuedAt(new Date())//簽發時間 58 .withSubject("subject").withAudience("100102134") 59 .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE_TIMEMILLS)) 60 //payload中加入自定義數據 61 .withClaim("name", "小明").withClaim("introduce", "TTT").sign(algorithm); 62 System.out.println("當前時間:" + new Date()); 63 System.out.println("jwt token:" + token); 64 return token; 65 } catch (JWTCreationException exception) { 66 //Invalid Signing configuration / Couldn't convert Claims. 67 throw exception; 68 } 69 } 70 71 public static Boolean verify(String token) { 72 try { 73 Algorithm algorithm = Algorithm.HMAC256(SECRET); 74 JWTVerifier verifier = JWT.require(algorithm).build(); //Reusable verifier instance 75 DecodedJWT jwt = verifier.verify(token); 76 77 String decodeHeader = StringUtils.newStringUtf8(Base64.decodeBase64(jwt.getHeader())); 78 String decodePayload = StringUtils.newStringUtf8(Base64.decodeBase64(jwt.getPayload())); 79 80 String signature = jwt.getSignature(); 81 String name = jwt.getClaim("name").asString(); 82 String introduce = jwt.getClaim("introduce").asString(); 83 84 System.out.println("header:" + jwt.getHeader()); 85 System.out.println("payload:" + jwt.getPayload()); 86 System.out.println("signature:" + signature); 87 88 System.out.println("headerString:" + decodeHeader); 89 System.out.println("payloadString:" + decodePayload); 90 91 System.out.println("name:" + name); 92 System.out.println("introduce:" + introduce); 93 return true; 94 } catch (JWTVerificationException exception) { 95 System.out.println("當前時間:" + new Date()); 96 System.out.println("驗證token失敗:" + exception.getMessage()); 97 return false; 98 } 99 } 100 101 public static void main(String[] args) { 102 String token = create(); 103 // try { 104 // Thread.sleep(3000l); 105 // } catch (InterruptedException e) { 106 // // TODO Auto-generated catch block 107 // e.printStackTrace(); 108 // } 109 Boolean result = verify(token); 110 System.out.println(result); 111 } 112 }
輸出結果:
當前時間:Wed Jan 27 10:15:44 CST 2021
jwt token:eyJkYXRlIjoiMjAyMi0wMS0wMSAxODowMCIsIndoZXJlIjoi5Z-O5Lic5bCP5qCR5p6XIiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJzdWJqZWN0IiwiYXVkIjoiMTAwMTAyMTM0IiwiaW50cm9kdWNlIjoiVFRUIiwibmFtZSI6IuWwj-aYjiIsImV4cCI6MTYxMTcxMzc1MCwiaWF0IjoxNjExNzEzNzQ0fQ.LQIg264ZYVpq8SfPpv8gwJ3WnZtn_yk8fH8Cwg9Z69k
header:eyJkYXRlIjoiMjAyMi0wMS0wMSAxODowMCIsIndoZXJlIjoi5Z-O5Lic5bCP5qCR5p6XIiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ
payload:eyJzdWIiOiJzdWJqZWN0IiwiYXVkIjoiMTAwMTAyMTM0IiwiaW50cm9kdWNlIjoiVFRUIiwibmFtZSI6IuWwj-aYjiIsImV4cCI6MTYxMTcxMzc1MCwiaWF0IjoxNjExNzEzNzQ0fQ
signature:LQIg264ZYVpq8SfPpv8gwJ3WnZtn_yk8fH8Cwg9Z69k
headerString:{"date":"2022-01-01 18:00","where":"城東小樹林","typ":"JWT","alg":"HS256"}
payloadString:{"sub":"subject","aud":"100102134","introduce":"TTT","name":"小明","exp":1611713750,"iat":1611713744}
name:小明
introduce:TTT
true