一、引入依赖(pom.xml)
1. JWT 依赖
xml
<!-- JWT 依赖,用于生成和验证令牌 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
2. 单元测试依赖(用于调试 JWT)
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
二、登录接口实现(含参数校验)
1. Controller 层代码
java
运行
@PostMapping("/login")
public Result login(
@Pattern(regexp = "^\\S{5,16}$", message = "用户名必须是5-16位非空字符") String username,
@Pattern(regexp = "^\\S{5,16}$", message = "密码必须是5-16位非空字符") String password
){
// 1. 根据用户名查询用户
User user = userService.findByUsername(username);
// 2. 判断用户是否存在 + 密码是否正确(需用 MD5 加密后比对)
if (user == null || !user.getPassword().equals(MD5Util.md5(password))){
return Result.error("用户名或密码错误");
}
// 3. 登录成功,生成 JWT 令牌并返回
String token = JwtUtil.generateToken(user.getId(), user.getUsername());
return Result.success(token);
}
2. 已有 Service & Mapper 层
UserService.findByUsername(username):复用注册时的查询方法,直接获取用户信息UserMapper.select * from user where username = ?:复用注册时的查询 SQL
三、JWT 原理与工具类实现
1. JWT 核心概念
JWT(JSON Web Token)是一种用于身份认证的令牌,由三部分组成:
- Header(头部) :记录令牌类型、签名算法(如
HS256) - Payload(有效载荷):携带业务数据(如用户 ID、用户名)和过期时间
- Signature(签名) :防止令牌被篡改,由
Header + Payload + 密钥加密生成
2. JWT 工具类(JwtUtil.java)
java
运行
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
// 签名密钥(生产环境请用更复杂的密钥)
private static final String SECRET_KEY = "itheima";
// 过期时间:3小时
private static final long EXPIRE_TIME = 1000 * 60 * 60 * 3;
// 生成 JWT 令牌
public static String generateToken(Integer id, String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("id", id);
claims.put("username", username);
return JWT.create()
.withClaim("user", claims)
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE_TIME))
.sign(Algorithm.HMAC256(SECRET_KEY));
}
// 解析验证 JWT 令牌
public static Map<String, Object> parseToken(String token) {
DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET_KEY))
.build()
.verify(token);
return decodedJWT.getClaim("user").asMap();
}
}
3. JWT 测试方法(单元测试)
java
运行
@Test
void testJwt() {
// 1. 生成令牌
String token = JwtUtil.generateToken(1, "张三");
System.out.println("生成的令牌:" + token);
// 2. 解析验证令牌
Map<String, Object> user = JwtUtil.parseToken(token);
System.out.println("解析结果:" + user);
}
四、JWT 关键注意事项
- 密钥必须配对 :生成和解析令牌时,必须使用同一个
SECRET_KEY,否则验证失败 - 令牌篡改 / 过期校验:解析时如果报错,说明令牌被篡改、过期或非法,需直接拒绝访问
- 令牌安全性 :
- 不要在 Payload 中存储敏感信息(如密码),仅存必要的业务数据
- 设置合理的过期时间,避免令牌永久有效
- 密钥需妥善保管,不要硬编码在代码中,可通过配置文件注入
五、登录认证的完整流程
- 用户输入用户名 / 密码,发送
/login请求 - 后端校验参数格式,查询用户信息并比对密码
- 验证通过后,生成包含用户信息的 JWT 令牌返回给前端
- 前端后续请求携带该令牌,后端解析验证通过后才允许访问资源