refactor(admin-server): 优化 JWT 认证过滤器
-放行 OPTIONS 预检请求,确保 CORS 配置正常工作 - 重构代码,提高可读性和可维护性 - 使用 Result 对象统一响应格式 - 优化错误处理和响应状态码
This commit is contained in:
parent
229dc941bb
commit
58907afa11
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue