JWT(JSON Web Token) 是一种开放标准(RFC 7519),用于在网络应用间安全地传输信息。它特别适用于 身份验证 和 授权 场景。
🎯 JWT 的核心组成
JWT 由三部分组成,格式为:Header.Payload.Signature
1. Header(头部)
{
"alg": "HS256", // 签名算法(HMAC SHA256)
"typ": "JWT" // 令牌类型
}
- Base64Url 编码后形成第一部分
2. Payload(负载/声明)
包含实际的用户数据和其他信息:
{
"sub": "1234567890", // 主题(用户ID)
"name": "John Doe", // 自定义声明
"iat": 1516239022, // 签发时间
"exp": 1516242622 // 过期时间
}
3. Signature(签名)
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
- 防止数据被篡改
📦 一个完整的 JWT 示例
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. // Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. // Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c // Signature
⚡ JWT 在 Java 中的使用
常用 Java JWT 库
- jjwt(最流行)
- Java JWT (Auth0)
- Nimbus JWT
Maven 依赖(jjwt 示例)
<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>
💻 Java 代码示例
1. 创建 JWT
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "mySecretKey123!@#";
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))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}
2. 验证和解析 JWT
public static boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
🔐 JWT 在 Web 应用中的典型流程
客户端 → 登录请求 → 服务器
↓
验证用户名密码
↓
生成JWT返回给客户端
↓
客户端 → 后续请求携带JWT(Authorization头)
↓
服务器验证JWT
↓
返回受保护资源
HTTP 请求头示例
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
✅ JWT 的优点
| 优点 | 说明 |
|---|---|
| 无状态 | 服务器不需要存储session,适合分布式系统 |
| 跨域友好 | 适合前后端分离、微服务架构 |
| 自包含 | 令牌包含所有必要信息,减少数据库查询 |
| 标准化 | 行业标准,各种语言都有成熟库 |
⚠️ JWT 的注意事项
安全问题
- 不要存储敏感信息(密码等)
- 设置合理的过期时间
- 使用 HTTPS 防止令牌被截获
- 签名密钥要足够复杂
性能考虑
// JWT 一旦签发就不可撤销
// 如果需要即时失效,需要额外方案:
// 1. 短过期时间 + 刷新令牌
// 2. 黑名单机制
// 3. 每次验证查库(会失去无状态优势)
🆚 JWT vs Session
| 对比项 | JWT | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务器端 |
| 跨域支持 | 好 | 需要额外配置 |
| 扩展性 | 好(无状态) | 一般(需要共享session) |
| 安全性 | 依赖签名 | 依赖session管理 |
| 撤销机制 | 复杂 | 简单 |
📊 实际应用场景
Spring Boot 集成示例
@Configuration
public class JwtConfig {
@Bean
public JwtUtil jwtUtil() {
return new JwtUtil();
}
}
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
// 验证用户
if (authenticate(request)) {
String token = jwtUtil.generateToken(request.getUsername());
return ResponseEntity.ok(new AuthResponse(token));
}
return ResponseEntity.status(401).build();
}
}
拦截器验证
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
if (jwtUtil.validateToken(token)) {
request.setAttribute("username", jwtUtil.getUsernameFromToken(token));
return true;
}
}
response.setStatus(401);
return false;
}
}
📚 最佳实践总结
- 使用安全的签名算法(HS256, RS256)
- 令牌有效期尽量短(15-30分钟为佳)
- 实现刷新令牌机制
- 存储在安全的地方(HttpOnly cookies)
- 处理令牌泄露(黑名单或短有效期)
- 避免在URL中传递(防止日志泄露)