package com.trafficaudit.security.filter;
|
|
import com.trafficaudit.security.utils.JwtUtils;
|
import org.springframework.core.annotation.Order;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
|
import javax.annotation.Resource;
|
import javax.servlet.FilterChain;
|
import javax.servlet.ServletException;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.util.Arrays;
|
import java.util.List;
|
|
/**
|
* 接口登录校验过滤器:/api/** 除白名单外必须携带有效 Bearer 令牌,否则直接返回 401。
|
* 白名单只保留登录前必须调用的接口(登录、行为验证码)。
|
*/
|
@Component
|
@Order(1)
|
public class JwtAuthFilter extends OncePerRequestFilter {
|
|
/** 免登录接口(登录页在拿到令牌前必须能调用) */
|
private static final List<String> WHITELIST = Arrays.asList(
|
"/api/auth/login",
|
"/api/auth/captcha",
|
"/api/auth/captcha/verify",
|
"/api/auth/captcha-config"
|
);
|
|
@Resource
|
private JwtUtils jwtUtils;
|
|
@Override
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
throws ServletException, IOException {
|
String uri = request.getRequestURI();
|
// 非接口请求(前端静态资源、首页)放行
|
if (uri == null || !uri.startsWith("/api")) {
|
chain.doFilter(request, response);
|
return;
|
}
|
// 预检请求放行,交由 CORS 处理
|
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
|
chain.doFilter(request, response);
|
return;
|
}
|
if (WHITELIST.contains(uri)) {
|
chain.doFilter(request, response);
|
return;
|
}
|
String username = jwtUtils.resolveUsername(request.getHeader("Authorization"));
|
if (username == null) {
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
response.setContentType("application/json;charset=UTF-8");
|
response.getWriter().write("{\"code\":401,\"message\":\"未登录或登录已过期\",\"data\":null}");
|
return;
|
}
|
request.setAttribute("loginUser", username);
|
chain.doFilter(request, response);
|
}
|
}
|