package com.vincent.rsf.openApi.security.filter; import com.vincent.rsf.openApi.entity.constant.Constants; import com.vincent.rsf.openApi.security.service.AppAuthService; import com.vincent.rsf.openApi.security.utils.TokenUtils; import lombok.extern.slf4j.Slf4j; import org.apache.tika.utils.StringUtils; 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.io.PrintWriter; /** * AppId和AppSecret认证过滤器 * * 用于验证请求头中的AppId和AppSecret * * @author vincent * @since 2026-01-05 */ @Slf4j @Component @Order(1) public class AppIdAuthenticationFilter extends OncePerRequestFilter { @Resource private AppAuthService appAuthService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); // 检查是否为认证请求(如获取token) if (isAuthRequest(requestURI)) { // 对于认证请求,允许通过 filterChain.doFilter(request, response); return; } String authHeader = request.getHeader(Constants.HEADER_AUTHORIZATION); if (authHeader != null) { String token = TokenUtils.extractTokenFromHeader(authHeader); if (token != null && TokenUtils.validateTokenTime(token)) { // Token时间认证成功,认证AppId和AppSecret String tokenAppId = TokenUtils.getAppIdFromToken(token); String tokenAppSecret = TokenUtils.getSecretFromToken(token); if (StringUtils.isBlank(tokenAppId) || StringUtils.isBlank(tokenAppSecret) || !appAuthService.validateApp(tokenAppId, tokenAppSecret)) { log.warn("Token验证失败"); sendErrorResponse(response, Integer.parseInt(Constants.UNAUTHENTICATED_CODE), "认证失败,请提供有效的Token"); return; } else { request.setAttribute(Constants.REQUEST_ATTR_APP_ID, tokenAppId); } } else { log.warn("Token验证失败或缺失"); sendErrorResponse(response, Integer.parseInt(Constants.UNAUTHENTICATED_CODE), "认证失败,请提供有效的Token"); return; } } else { log.warn("缺少Token认证信息"); sendErrorResponse(response, Integer.parseInt(Constants.UNAUTHENTICATED_CODE), "认证失败,请提供有效的Token"); return; } filterChain.doFilter(request, response); } /** * 发送错误响应 * * @param response HTTP响应 * @param code 错误码 * @param message 错误消息 * @throws IOException */ private void sendErrorResponse(HttpServletResponse response, int code, String message) throws IOException { response.setStatus(code); response.setContentType("application/json;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.write("{\"code\": \"" + code + "\", \"msg\": \"" + message + "\", \"data\": null}"); writer.flush(); } /** * 检查是否为认证请求(不需要认证的请求) * * @param requestURI 请求URI * @return 是否为认证请求 */ private boolean isAuthRequest(String requestURI) { return requestURI.contains("/getToken"); // || requestURI.contains("/auth/validate") || // requestURI.contains("/auth/login"); } @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { String requestURI = request.getRequestURI(); // 不过滤认证相关请求和公开接口 return requestURI.contains("/auth/") || requestURI.contains("/public/") || requestURI.contains("/doc.html") || requestURI.contains("/swagger") || requestURI.contains("/webjars") || requestURI.contains("/v2/api-docs") || requestURI.contains("/v3/api-docs"); } }