JWT令牌详解及Java中的使用实战
摘要
本文将深入解析**JWT(JSON Web Token)**的核心概念,通过图文并茂的方式详解其工作原理,并手把手教你在Java中实现JWT的生成、验证与解析。无论你是认证授权新手还是想巩固知识的老手,都能在这里找到实用干货!
目录
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(头部)
json
{
"alg": "HS256", // 签名算法
"typ": "JWT" // 令牌类型
}
→ Base64Url编码后形成第一部分
2.1.2 Payload(载荷)
包含声明(Claims),分为三类:
- 注册声明 (预定义字段,如
exp
过期时间) - 公共声明(自定义但需避免冲突)
- 私有声明(业务自定义数据)
示例:
json
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
→ Base64Url编码后形成第二部分
2.1.3 Signature(签名)
通过指定算法对前两部分签名,确保数据完整。以HS256为例:
java
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey)
3. Java实现JWT实战
3.1 环境准备
推荐使用JJWT库(目前最流行的Java JWT库):
Maven依赖:
xml
<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令牌
java
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
java
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格式
示例:
java
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`)