refactor(admin-server): 优化 JWT 认证过滤器

-放行 OPTIONS 预检请求,确保 CORS 配置正常工作
- 重构代码,提高可读性和可维护性
- 使用 Result 对象统一响应格式
- 优化错误处理和响应状态码
This commit is contained in:
FalingCliff 2025-05-25 15:19:18 +08:00
parent 229dc941bb
commit 58907afa11
1 changed files with 24 additions and 12 deletions

View File

@ -1,7 +1,10 @@
package com.example.admin_server.filter; package com.example.admin_server.filter;
import com.example.admin_server.common.Result;
import com.example.admin_server.constant.AuthConst; import com.example.admin_server.constant.AuthConst;
import com.example.admin_server.enums.ResultCode;
import com.example.admin_server.utils.JwtUtil; import com.example.admin_server.utils.JwtUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -22,7 +25,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil; private final JwtUtil jwtUtil;
// 白名单路径登录接口一般放这里
private static final Set<String> WHITELIST = new HashSet<>(); private static final Set<String> WHITELIST = new HashSet<>();
static { static {
@ -30,7 +32,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
WHITELIST.add("/api/client/login"); WHITELIST.add("/api/client/login");
WHITELIST.add("/api/employee/login"); WHITELIST.add("/api/employee/login");
WHITELIST.add("/api/client/wx/login"); WHITELIST.add("/api/client/wx/login");
// 也可以放其它公开接口
} }
public JwtAuthenticationFilter(JwtUtil jwtUtil) { public JwtAuthenticationFilter(JwtUtil jwtUtil) {
@ -42,45 +43,56 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
@NonNull HttpServletResponse response, @NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException { @NonNull FilterChain filterChain) throws ServletException, IOException {
String method = request.getMethod();
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
// 如果路径在白名单放行
// 放行预检请求 OPTIONS避免被拦截导致 CORS 失败
if ("OPTIONS".equalsIgnoreCase(method)) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
// 白名单路径放行
if (WHITELIST.contains(requestURI)) { if (WHITELIST.contains(requestURI)) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
} }
// 🔒 获取 token根据路径区分前后台
String token = null; String token = null;
if (requestURI.startsWith("/api/admin/")) { if (requestURI.startsWith("/api/admin/")) {
token = request.getHeader(AuthConst.ADMIN_AUTHORIZATION_HEADER); token = request.getHeader(AuthConst.ADMIN_AUTHORIZATION_HEADER);
} else if (requestURI.startsWith("/api/client/")) { } else if (requestURI.startsWith("/api/client/")) {
token = request.getHeader(AuthConst.FRONT_AUTHORIZATION_HEADER); token = request.getHeader(AuthConst.FRONT_AUTHORIZATION_HEADER);
} else { } else {
// 鉴权路径放行 // 鉴权路径放行
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
} }
if (!StringUtils.hasText(token)) { if (!StringUtils.hasText(token)) {
writeResponse(response, 401, "{\"code\":400,\"msg\":\"未登录缺少token\"}"); writeJsonResponse(response,
Result.fail(ResultCode.NOT_LOGIN.getCode(), "未登录:缺少 token"));
return; return;
} }
Optional<Claims> claimsOpt = jwtUtil.parseToken(token); Optional<Claims> claimsOpt = jwtUtil.parseToken(token);
if (!claimsOpt.isPresent() || jwtUtil.isTokenExpired(token)) { if (!claimsOpt.isPresent() || jwtUtil.isTokenExpired(token)) {
writeResponse(response, 401, "{\"code\":401,\"msg\":\"未授权token无效或过期\"}"); writeJsonResponse(response,
Result.fail(ResultCode.UNAUTHORIZED.getCode(), "未授权token 无效或过期"));
return; return;
} }
// 可以把用户信息放到SecurityContextHolder或request里 // TODO: 可以 setAttribute SecurityContextHolder 存放用户信息
// SecurityContextHolder.getContext().setAuthentication(...)
// request.setAttribute("claims", claimsOpt.get());
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} }
private void writeResponse(HttpServletResponse response, int status, String json) throws IOException { private void writeJsonResponse(HttpServletResponse response, Result<?> result) throws IOException {
response.setStatus(status); response.setStatus(HttpServletResponse.SC_OK);
response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write(json); ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(result));
} }
} }