This commit is contained in:
2025-12-12 14:32:14 +08:00
27 changed files with 43179 additions and 387 deletions

View File

@@ -16,4 +16,4 @@ public class ProcessInstanceInfo {
private Long durationInMillis;
private String durationFormatted;
private String status; // "pending""running" 或 "completed"
}
}

View File

@@ -0,0 +1,118 @@
package com.sdm.common.filter;
import com.sdm.common.common.ThreadLocalContext;
import com.sdm.common.config.WhitelistProperties;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import java.io.IOException;
import java.util.List;
@Slf4j
public abstract class BaseAuthFilter implements Filter {
@Autowired
protected WhitelistProperties whitelistProperties;
protected List<String> excludedPaths;
protected final AntPathMatcher pathMatcher = new AntPathMatcher();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
// 从初始化参数中读取白名单
if (whitelistProperties != null) {
excludedPaths = whitelistProperties.getPaths();
}
log.info("----------- BaseAuthFilter init ----------");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest) servletRequest;
// 1尝试从Header中加载用户信息到ThreadLocal (无论是否在白名单,都尝试加载)
boolean hasContext = ThreadLocalContext.verifyRequest(req);
// 检查是否在白名单中(如果子类需要此功能)
if (shouldCheckWhitelist() && isWhitelisted(req)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
// 执行认证检查
if (!shouldSkipAuthentication(req) && !hasContext) {
handleUnauthenticatedRequest(servletResponse);
return;
}
// 允许子类添加额外的处理逻辑
processAuthenticatedRequest(req, servletResponse);
}
filterChain.doFilter(servletRequest, servletResponse);
}
/**
* 是否应该跳过认证检查
* 子类可以覆盖此方法来实现特定逻辑
*/
protected boolean shouldSkipAuthentication(HttpServletRequest request) {
return false;
}
/**
* 是否应该检查白名单
* 子类可以覆盖此方法来控制是否启用白名单功能
*/
protected boolean shouldCheckWhitelist() {
return excludedPaths != null && !excludedPaths.isEmpty();
}
/**
* 检查请求路径是否在白名单中
*/
protected boolean isWhitelisted(HttpServletRequest request) {
String path = request.getRequestURI().substring(request.getContextPath().length());
for (String excludedPath : excludedPaths) {
if (pathMatcher.match(excludedPath, path)) {
return true;
}
}
return false;
}
/**
* 处理未认证的请求
*/
protected void handleUnauthenticatedRequest(ServletResponse servletResponse) throws IOException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"message\":\"未登录或认证信息缺失\"}");
}
/**
* 处理已认证的请求
* 子类可以覆盖此方法来添加额外的处理逻辑
*/
protected void processAuthenticatedRequest(HttpServletRequest request, ServletResponse servletResponse) throws IOException, ServletException {
// 默认不执行任何操作,供子类重写
}
@Override
public void destroy() {
Filter.super.destroy();
log.info("----------- BaseAuthFilter destroy ----------");
}
}