JWT令牌详解及Java中的使用实战
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`)