本文目录导读:

这是一个关于Java实现JWT(JSON Web Token)的完整案例教程,我将从依赖引入、核心工具类、生成与验证Token,到实际在Spring Boot项目中的应用,一步步为你说明。
添加Maven依赖
在你的 pom.xml 中添加JWT相关的依赖,最常用的是 jjwt 库。
<dependencies>
<!-- JWT核心库 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<!-- Spring Boot Web (如果你是用Spring Boot) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
注意:
jjwt-api是编译依赖,jjwt-impl和jjwt-jackson是运行时依赖(运行和测试时需要)。
创建JWT工具类
这是一个通用的JWT工具类,包含生成Token、解析Token、验证Token 的核心方法。
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
public class JwtUtil {
// 1. 签名密钥(生产环境建议使用Base64编码的强密钥,不要硬编码)
private static final String SECRET = "YourSuperSecretKeyForJWT2024YoursMustBeAtLeast256BitsLong!!";
// 2. Token有效期(毫秒),这里设为1小时
private static final long EXPIRATION = 3600_000L;
// 3. 生成签名密钥对象
private static SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));
}
// 4. 生成JWT Token
public static String generateToken(String userId, String username) {
Date now = new Date();
Date expirationDate = new Date(now.getTime() + EXPIRATION);
return Jwts.builder()
.subject(userId) // 主题:用户ID
.claim("username", username) // 自定义声明
.issuedAt(now) // 签发时间
.expiration(expirationDate) // 过期时间
.signWith(getSigningKey()) // 签名
.compact();
}
// 5. 解析Token,获取Claims(包含所有声明)
public static Claims parseToken(String token) {
return Jwts.parser()
.verifyWith(getSigningKey()) // 验证签名
.build()
.parseSignedClaims(token)
.getPayload();
}
// 6. 从Token中获取用户ID(即subject)
public static String getUserId(String token) {
return parseToken(token).getSubject();
}
// 7. 判断Token是否过期
public static boolean isTokenExpired(String token) {
try {
Claims claims = parseToken(token);
return claims.getExpiration().before(new Date());
} catch (ExpiredJwtException e) {
return true;
}
}
// 8. 验证Token是否有效(未过期且签名正确)
public static boolean validateToken(String token) {
try {
parseToken(token);
return !isTokenExpired(token);
} catch (JwtException | IllegalArgumentException e) {
// 签名无效、格式错误、过期等均视为无效
return false;
}
}
}
关键点说明
- 签名密钥:
SECRET至少需要256位(32字节),否则jjwt会报错。 - 声明(Claims):
subject通常存储用户唯一标识(如用户ID),自定义信息通过claim()添加。 - 验证:
verifyWith()方法会自动验证签名是否匹配。
在Spring Boot中集成JWT(示例)
1 用户登录接口(返回Token)
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
// 1. 实际项目中这里应该验证用户名密码(此处简化)
if (!"admin".equals(request.getUsername())
|| !"123456".equals(request.getPassword())) {
return ResponseEntity.status(401).body("用户名或密码错误");
}
// 2. 验证通过,生成JWT Token
String userId = "1001"; // 假设从数据库获取
String token = JwtUtil.generateToken(userId, request.getUsername());
// 3. 返回Token给客户端
return ResponseEntity.ok(new LoginResponse(token));
}
}
// 请求体
class LoginRequest {
private String username;
private String password;
// 省略 getter/setter
}
// 响应体
class LoginResponse {
private String token;
public LoginResponse(String token) { this.token = token; }
// 省略 getter/setter
}
2 添加JWT拦截器(验证Token)
创建一个过滤器,拦截非登录请求并验证Token。
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
// 1. 放行登录接口
if (request.getRequestURI().equals("/api/auth/login")) {
filterChain.doFilter(request, response);
return;
}
// 2. 从请求头获取Token(格式:Bearer <token>)
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
sendError(response, "缺少Token");
return;
}
String token = authHeader.substring(7); // 去掉"Bearer "
// 3. 验证Token
if (!JwtUtil.validateToken(token)) {
sendError(response, "Token无效或已过期");
return;
}
// 4. Token有效,将用户信息存入请求上下文(后续Controller可用)
String userId = JwtUtil.getUserId(token);
request.setAttribute("userId", userId);
// 5. 继续执行后续过滤器链
filterChain.doFilter(request, response);
}
private void sendError(HttpServletResponse response, String message)
throws IOException {
response.setStatus(401);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("{\"error\":\"" + message + "\"}");
}
}
3 注册过滤器(Spring Boot配置)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private JwtAuthenticationFilter jwtFilter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtFilter)
.addPathPatterns("/api/**") // 拦截所有/api下的请求
.excludePathPatterns("/api/auth/**"); // 排除登录
}
}
测试流程
1 获取Token
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"123456"}'
响应:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMDAxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTcwMDAwMDAwMCwiZXhwIjoxNzAwMDAzNjAwfQ.xxxxxx"
}
2 携带Token访问受保护接口
curl http://localhost:8080/api/users/profile \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."
常见问题与优化建议
| 问题 | 解决方案 |
|---|---|
| 密钥硬编码不安全 | 将密钥放在 application.yml 中,通过 @Value 注入 |
| Token无法刷新 | 实现刷新Token机制(参考OAuth2,返回access_token + refresh_token) |
| Token在黑名单中 | 使用Redis存储已注销的Token(如在用户登出时) |
| 不支持无状态 | JWT本身是无状态的,但黑名单方案会引入状态,根据需求取舍 |
优化后的密钥配置(application.yml)
jwt: secret: YourSuperSecretKeyForJWT2024YoursMustBeAtLeast256BitsLong!! expiration: 3600000 # 毫秒
然后在工具类中使用 @Value 注入:
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
// ... 其余代码改为非静态方法
}
通过以上案例,你实现了:
- ✅ 生成JWT:包含用户标识和自定义声明,设置过期时间。
- ✅ 验证JWT:检查签名完整性、是否过期。
- ✅ 集成Spring Boot:通过过滤器自动验证每个API请求的Token。
- ✅ 安全实践:强密钥、统一错误返回、可配置化密钥。
这个结构可以直接应用于你的项目,只需根据业务调整用户信息的内容和验证逻辑即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播