| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- package com.malk.controller;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.nio.charset.StandardCharsets;
- import java.security.MessageDigest;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.List;
- /**
- * 生产管理接口保护:默认关闭;临时开启时必须同时配置并携带管理令牌。
- */
- @Slf4j
- @Configuration
- public class AdminEndpointGuardConfig implements WebMvcConfigurer {
- static final String TOKEN_HEADER = "X-AKDS-Admin-Token";
- static final List<String> PROTECTED_PATHS = Collections.unmodifiableList(Arrays.asList(
- "/workhours/**",
- "/personnel-sync/**",
- "/approval/writeback/sync",
- "/approval/resubmit",
- "/timecard/summary/cleanup-duplicates",
- "/timecard/summary/delete-instances"
- ));
- @Value("${admin-api.enabled:false}")
- private boolean enabled;
- @Value("${admin-api.token:}")
- private String token;
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new AdminEndpointInterceptor(enabled, token))
- .addPathPatterns(PROTECTED_PATHS);
- }
- static final class AdminEndpointInterceptor implements HandlerInterceptor {
- private final boolean enabled;
- private final String expectedToken;
- AdminEndpointInterceptor(boolean enabled, String expectedToken) {
- this.enabled = enabled;
- this.expectedToken = expectedToken;
- }
- @Override
- public boolean preHandle(
- HttpServletRequest request,
- HttpServletResponse response,
- Object handler) throws Exception {
- response.setHeader("Cache-Control", "no-store");
- if (!enabled) {
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- return false;
- }
- String actualToken = request.getHeader(TOKEN_HEADER);
- if (!tokenMatches(expectedToken, actualToken)) {
- log.warn("[AdminAPI] 管理接口鉴权失败 method={} path={} remote={}",
- request.getMethod(), request.getRequestURI(), request.getRemoteAddr());
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
- return false;
- }
- return true;
- }
- }
- static boolean tokenMatches(String expectedToken, String actualToken) {
- if (StringUtils.isBlank(expectedToken) || StringUtils.isBlank(actualToken)) {
- return false;
- }
- return MessageDigest.isEqual(
- expectedToken.getBytes(StandardCharsets.UTF_8),
- actualToken.getBytes(StandardCharsets.UTF_8));
- }
- }
|