JWT令牌詳解及Java中的使用實戰
摘要
本文將深入解析**JWT(JSON Web Token)**的核心概念,通過圖文并茂的方式詳解其工作原理,并手把手教你在Java中實現JWT的生成、驗證與解析。無論你是認證授權新手還是想鞏固知識的老手,都能在這里找到實用干貨!
目錄
- 什么是JWT?
- JWT結構剖析
- Java實現JWT實戰
- 核心API詳解
- 安全指南
- 總結
1. 什么是JWT?
1.1 基本定義
JWT(JSON Web Token) 是一種輕量級的開放標準(RFC 7519),用于在各方之間安全傳輸JSON格式信息。其典型應用場景包括:
- 🔑 身份認證(如替代Session)
- 🔒 跨服務安全通信
- 🌐 跨域認證(如OAuth2)
1.2 核心優勢
特性 | 說明 |
---|---|
無狀態 | 服務端無需存儲會話信息 |
跨語言支持 | 所有主流語言均有成熟實現庫 |
自包含性 | 令牌自身攜帶用戶信息及元數據 |
防篡改 | 基于簽名機制保障數據完整性 |
2. JWT結構剖析
2.1 令牌組成
JWT由三部分通過.
連接組成:
header.payload.signature
2.1.1 Header(頭部)
{"alg": "HS256", // 簽名算法"typ": "JWT" // 令牌類型
}
→ Base64Url編碼后形成第一部分
2.1.2 Payload(載荷)
包含聲明(Claims),分為三類:
- 注冊聲明(預定義字段,如
exp
過期時間) - 公共聲明(自定義但需避免沖突)
- 私有聲明(業務自定義數據)
示例:
{"sub": "1234567890","name": "John Doe","admin": true,"iat": 1516239022
}
→ Base64Url編碼后形成第二部分
2.1.3 Signature(簽名)
通過指定算法對前兩部分簽名,確保數據完整。以HS256為例:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secretKey)
3. Java實現JWT實戰
3.1 環境準備
推薦使用JJWT庫(目前最流行的Java JWT庫):
Maven依賴:
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
3.2 生成JWT令牌
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;public class JwtDemo {// 生成安全密鑰(HS256需要至少256位)private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);private static final long EXPIRATION_TIME = 86400000; // 24小時public static String generateToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).claim("role", "admin") // 添加自定義聲明.signWith(SECRET_KEY).compact();}
}
3.3 解析驗證JWT
public static Claims parseToken(String token) {return Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody();
}// 使用示例
public static void main(String[] args) {String token = generateToken("user1");System.out.println("Generated Token: " + token);Claims claims = parseToken(token);System.out.println("Subject: " + claims.getSubject());System.out.println("Expiration: " + claims.getExpiration());System.out.println("Role: " + claims.get("role"));
}
4. 核心API詳解
4.1 Jwts.builder() 方法鏈
方法 | 作用 |
---|---|
setSubject() | 設置主題(通常是用戶ID) |
setIssuedAt() | 設置令牌簽發時間 |
setExpiration() | 設置過期時間 |
claim(key, value) | 添加自定義聲明 |
signWith(key) | 指定簽名密鑰和算法 |
4.2 異常處理
解析時需捕獲以下異常:
SignatureException
: 簽名不匹配MalformedJwtException
: 令牌結構錯誤ExpiredJwtException
: 令牌已過期UnsupportedJwtException
: 不支持的JWT格式
示例:
try {Claims claims = parseToken(token);
} catch (ExpiredJwtException ex) {System.out.println("令牌已過期!");
} catch (SignatureException ex) {System.out.println("簽名驗證失敗!");
}
5. 安全指南
-
密鑰管理
- 生產環境避免硬編碼密鑰
- 推薦使用密鑰管理系統(如HashiCorp Vault)
-
傳輸安全
- 必須通過HTTPS傳輸JWT
- 避免URL參數傳遞(可能被日志記錄)
-
存儲策略
- 瀏覽器端建議使用
HttpOnly
的Cookie - 移動端使用安全存儲(如Android Keystore)
- 瀏覽器端建議使用
-
最佳實踐
- 設置合理的過期時間(建議≤24小時)
- 敏感操作要求重新認證
- 定期輪換簽名密鑰
6. 總結
通過本文,你應當已經掌握:
- ? JWT的核心組成與工作原理
- ? 在Java中生成/解析JWT的具體實現
- ? 安全使用JWT的最佳實踐
Q&A: 歡迎評論區提問交流!👨💻
注:
1. 實際使用時請替換示例中的GitHub地址、博客鏈接和圖片URL
2. HS256的密鑰生成方式僅用于演示,生產環境需使用更安全的密鑰管理方案
3. 建議在Web應用中結合過濾器進行JWT校驗(如Spring Security的`OncePerRequestFilter`)