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中传递(防止日志泄露)