JWT令牌、过滤器、拦截器、全局异常处理器 的系统性总结

1 阅读3分钟

1. JWT(JSON Web Token)

核心概念

  • 作用:轻量级身份验证和授权机制,替代传统的Session。

  • 结构Header.Payload.Signature

    • Header:算法类型(如HS256)和Token类型(JWT)。
    • Payload:用户信息(如用户ID、角色)、过期时间等。
    • Signature:对Header和Payload的签名,防篡改。
  • 流程

    1. 用户登录后,服务端生成JWT返回给客户端。
    2. 客户端后续请求携带JWT(通常放在 Authorization 头)。
    3. 服务端验证JWT合法性并解析用户信息。

示例代码(使用 jjwt 库)

public class JwtUtils {
    private static final String SECRET_KEY = "your-secret-key";
    private static final long EXPIRATION = 86400000; // 24小时

    // 生成JWT
    public static String generateToken(String username, List<String> roles) {
        return Jwts.builder()
                .setSubject(username)
                .claim("roles", roles)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    // 解析JWT
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
}

2. 过滤器(Filter)

核心概念

  • 作用:在请求进入Servlet前预处理(如身份验证、日志记录)。

  • 执行位置:Servlet容器层(Tomcat/Jetty)。

  • 特点:可拦截所有请求(包括静态资源)。

  • 常见用途

    • 身份验证(如JWT校验)。
    • 请求日志记录。
    • 字符编码处理。

示例代码(JWT认证过滤器)

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            try {
                Claims claims = JwtUtils.parseToken(token);
                String username = claims.getSubject();
                List<String> roles = claims.get("roles", List.class);
                // 构建Spring Security认证对象
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                    username, null, roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList())
                );
                SecurityContextHolder.getContext().setAuthentication(auth);
            } catch (Exception e) {
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}

3. 拦截器(Interceptor)

核心概念

  • 作用:在Controller方法执行前后处理逻辑(如权限校验、参数预处理)。

  • 执行位置:Spring MVC层(DispatcherServlet之后)。

  • 特点:可访问Spring上下文(如Controller、Service)。

  • 常见用途

    • 接口访问频率控制。
    • 参数校验。
    • 动态权限控制。

示例代码(权限拦截器)

public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 检查用户权限(如是否拥有特定角色)
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth == null || !auth.getAuthorities().contains(new SimpleGrantedAuthority("ADMIN"))) {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            return false;
        }
        return true;
    }
}

// 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/admin/**");
    }
}

4. 全局异常处理器

核心概念

  • 作用:统一处理Controller层抛出的异常,返回标准化错误响应。

  • 核心注解

    • @ControllerAdvice:声明全局异常处理器。
    • @ExceptionHandler:定义处理特定异常的方法。

示例代码

@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理认证异常
    @ExceptionHandler(AuthenticationException.class)
    @ResponseBody
    public ResponseEntity<?> handleAuthException(AuthenticationException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", e.getMessage()));
    }

    // 处理其他未知异常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<?> handleException(Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of("error", "Internal Server Error"));
    }
}

协作关系与执行顺序

  1. 请求流程
    Filter(JWT校验) → Interceptor(权限检查) → Controller → 全局异常处理器

  2. 异常处理

    • Filter和Interceptor中的异常默认不会由 @ControllerAdvice 捕获。
    • 需在Filter中通过 try-catch 处理异常或自定义异常转发。

关键对比

组件执行层级是否依赖Spring典型用途
FilterServlet容器层全局请求处理(如JWT校验)
InterceptorSpring MVC层细粒度权限控制、日志记录
@ControllerAdviceSpring MVC层统一异常处理、响应格式化

完整流程示例

  1. 用户登录:生成JWT并返回。
  2. 请求携带JWT:客户端在 Authorization 头中添加 Bearer <token>
  3. JWT过滤器:解析Token并设置Spring Security上下文。
  4. 拦截器:检查用户权限,决定是否放行。
  5. Controller:执行业务逻辑。
  6. 异常处理:若Controller抛出异常,由 @ControllerAdvice 统一处理。

最佳实践

  • JWT安全

    • 使用HTTPS传输。
    • 设置合理的过期时间。
    • 避免在JWT中存储敏感信息。
  • 过滤器 vs 拦截器

    • 优先用拦截器处理与Spring相关的逻辑(如依赖注入)。
    • 过滤器处理底层Servlet逻辑(如编码、跨域)。
  • 异常处理

    • 在Filter中手动处理异常并返回标准响应。
    • 使用 @ControllerAdvice 统一格式化错误响应。