以下是基于JWT的登录校验模块化实现方案,分为 JWT工具类、登录认证模块、拦截器模块、配置模块 四大核心模块,代码结构清晰且职责分明。
一、模块划分与职责说明
| 模块名称 | 职责描述 | 关键类/文件 |
|---|---|---|
| JWT工具类 | 生成、解析、验证JWT令牌 | JwtUtils.java |
| 登录认证模块 | 验证用户信息,生成并下发JWT令牌 | AuthController.java |
| 拦截器模块 | 拦截请求并校验JWT令牌有效性 | JwtAuthInterceptor.java |
| 配置模块 | 注册拦截器,配置拦截路径和排除路径 | WebMvcConfig.java |
导入相关依赖
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT库 -->
<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>
二、JWT工具类模块(核心代码)
职责:生成令牌、解析令牌、验证签名和过期时间
1、创建配置文件(application.yml)
# application.yml
jwt:
secret: "my-256-bit-secret-key" # 建议生成随机256位以上字符串
expiration: 3600000 # 过期时间(单位:毫秒,此处为1小时)
2.JWT工具类
@Component
public class JwtUtils {
// 从配置文件中注入密钥和过期时间(避免硬编码)
@Value("${jwt.secret}")
private String secretKey;
@Value("${jwt.expiration}")
private long expiration;
/**
* 生成JWT令牌
* @param userId 用户唯一标识
* @param claims 自定义声明(如角色)
*/
public String generateToken(String userId, Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setSubject(userId)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
/**
* 解析并验证JWT令牌
*/
public Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody();
}
/**
* 校验令牌是否过期或被篡改
*/
public boolean validateToken(String token) {
try {
parseToken(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
}
三、登录认证模块(伪代码)
职责:验证用户登录信息,返回JWT令牌
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private JwtUtils jwtUtils;
// 用户已实现的验证逻辑(伪代码)
@Autowired
private UserService userService;
@PostMapping("/login")
public Result login(@RequestBody LoginRequest request) {
// 1. 调用用户实现的验证逻辑
User user = userService.authenticate(request.getUsername(), request.getPassword());
// 2. 生成JWT令牌
Map<String, Object> claims = new HashMap<>();
claims.put("role", user.getRole()); // 添加角色声明
String token = jwtUtils.generateToken(user.getId(), claims);
// 3. 返回令牌
return Result.success("登录成功", token);
}
}
四、拦截器模块(核心代码)

职责:拦截请求并校验JWT令牌有效性
这一段拦截器的代码需要了解前端是如何来存储下发的token令牌的然后每次操作需要校验一下这个token是否合法。(下面这个是一个例子)
@Component
public class JwtAuthInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtils jwtUtils;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 1. 从请求头提取令牌
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
sendError(response, 401, "未提供有效令牌");
return false;
}
token = token.substring(7); // 去除"Bearer "前缀
// 2. 校验令牌
if (!jwtUtils.validateToken(token)) {
sendError(response, 403, "令牌无效或已过期");
return false;
}
// 3. 解析用户信息并存入请求上下文
Claims claims = jwtUtils.parseToken(token);
request.setAttribute("userId", claims.getSubject());
request.setAttribute("role", claims.get("role"));
return true;
}
// 统一返回错误信息
private void sendError(HttpServletResponse response, int code, String message) {
response.setStatus(code);
response.setContentType("application/json");
try {
response.getWriter().write("{\"code\":" + code + ", \"message\":\"" + message + "\"}");
} catch (IOException ignored) {}
}
}
五、配置模块(关键配置)
职责:注册拦截器,配置拦截规则
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private JwtAuthInterceptor jwtAuthInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtAuthInterceptor)
.addPathPatterns("/api/**") // 拦截所有API请求
.excludePathPatterns( // 排除无需校验的路径
"/auth/login",
"/swagger-ui/**",
"/v3/api-docs/**"
);
}
}
六、安全增强建议
- HTTPS传输:确保生产环境启用HTTPS,防止令牌被窃取。
- 密钥管理:将
jwt.secret和jwt.expiration写入配置文件(如application.yml),避免硬编码。jwt: secret: "your-256-bit-secret-key" # 推荐使用256位以上随机字符串 expiration: 3600000 # 1小时有效期(单位:毫秒) - 令牌刷新机制:可结合刷新令牌(Refresh Token)延长会话有效期。
- 黑名单机制:在拦截器中校验令牌是否已被主动注销(如通过Redis记录失效令牌)。
七、全局异常处理(可选补充)
若需要在拦截器中触发全局异常处理器,可通过转发请求到Controller层:
// 在拦截器中捕获异常后转发
request.getRequestDispatcher("/error-handler").forward(request, response);
// 定义全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
@RequestMapping("/error-handler")
public Result handleFilterException(HttpServletRequest request) {
Exception ex = (Exception) request.getAttribute("filter.error");
return Result.error(ex.getMessage());
}
}
通过以上模块化设计,实现了 登录认证 → 令牌下发 → 请求拦截 → 安全校验 的完整链路,各模块职责明确,便于维护和扩展。

被折叠的 条评论
为什么被折叠?



