feat(config): 支持配置中心动态跳过指定用户签名校验

This commit is contained in:
2026-03-23 13:19:59 +08:00
parent eaf015fe48
commit b1ef4ee192
3 changed files with 38 additions and 3 deletions

View File

@@ -1,7 +1,10 @@
package com.yolo.keyborad.interceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.yolo.keyborad.config.AppConfig;
import com.yolo.keyborad.config.NacosAppConfigCenter;
import com.yolo.keyborad.utils.SignUtils;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.http.HttpServletRequest;
@@ -25,6 +28,7 @@ public class SignInterceptor implements HandlerInterceptor {
private final ObjectMapper signValueObjectMapper = new ObjectMapper()
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
private final StringRedisTemplate redisTemplate;
private final NacosAppConfigCenter.DynamicAppConfig cfgHolder;
// 允许时间误差 20秒
private static final long ALLOW_TIME_DIFF_SECONDS = 200;
@@ -32,9 +36,11 @@ public class SignInterceptor implements HandlerInterceptor {
private static final long NONCE_EXPIRE_SECONDS = 300;
public SignInterceptor(Map<String, String> appSecretMap,
StringRedisTemplate redisTemplate) {
StringRedisTemplate redisTemplate,
NacosAppConfigCenter.DynamicAppConfig cfgHolder) {
this.appSecretMap = appSecretMap;
this.redisTemplate = redisTemplate;
this.cfgHolder = cfgHolder;
}
@Override
@@ -43,6 +49,9 @@ public class SignInterceptor implements HandlerInterceptor {
if (request.getDispatcherType() != DispatcherType.REQUEST) {
return true;
}
if (shouldSkipSignValidation()) {
return true;
}
String appId = request.getHeader("X-App-Id");
String timestamp = request.getHeader("X-Timestamp");
@@ -121,6 +130,21 @@ public class SignInterceptor implements HandlerInterceptor {
return true;
}
private boolean shouldSkipSignValidation() {
AppConfig appConfig = cfgHolder.getRef().get();
if (appConfig == null || appConfig.getSkipUser() == null) {
return false;
}
List<Integer> skipList = appConfig.getSkipUser().getSkipList();
if (skipList == null || skipList.isEmpty()) {
return false;
}
long userId = StpUtil.getLoginIdAsLong();
return skipList.stream()
.filter(Objects::nonNull)
.anyMatch(skipUserId -> skipUserId.longValue() == userId);
}
private String stringifyForSign(Object value) {
if (value == null) {
return null;

View File

@@ -3,6 +3,7 @@ package com.yolo.keyborad.config;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/*
* @author: ziin
@@ -21,6 +22,8 @@ public class AppConfig {
private customerMailConfig customerMailConfig = new customerMailConfig();
private skipUser skipUser = new skipUser();
@Data
public static class UserRegisterProperties {
@@ -41,6 +44,11 @@ public class AppConfig {
private Integer vectorSearchLimit = 1;
}
@Data
public static class skipUser{
private List<Integer> skipList = null;
}
@Data
public static class LLmConfig {
//LLM系统提示语

View File

@@ -22,9 +22,12 @@ import java.util.HashMap;
public class SaTokenConfigure implements WebMvcConfigurer {
private final StringRedisTemplate redisTemplate;
private final NacosAppConfigCenter.DynamicAppConfig cfgHolder;
public SaTokenConfigure(StringRedisTemplate redisTemplate) {
public SaTokenConfigure(StringRedisTemplate redisTemplate,
NacosAppConfigCenter.DynamicAppConfig cfgHolder) {
this.redisTemplate = redisTemplate;
this.cfgHolder = cfgHolder;
}
HashMap<String, String> appSecretMap = new HashMap<>();
@@ -53,7 +56,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
.addPathPatterns("/**")
.excludePathPatterns(getExcludePaths());
appSecretMap.put(appId, appSecret);
registry.addInterceptor(new SignInterceptor(appSecretMap,redisTemplate))
registry.addInterceptor(new SignInterceptor(appSecretMap, redisTemplate, cfgHolder))
.addPathPatterns("/**") // 需要签名校验的接口
.excludePathPatterns(getExcludePaths()); // 不需要校验的接口;
}