This commit is contained in:
2026-06-20 17:28:24 +08:00
parent 8ae0609bed
commit 6fe2cc9480
16 changed files with 254 additions and 153 deletions

View File

@@ -8,12 +8,14 @@ import (
"tyapi-server/internal/domains/api/entities"
"tyapi-server/internal/domains/api/repositories"
"tyapi-server/internal/domains/api/services/processors"
"go.uber.org/zap"
)
type QueryWhitelistService interface {
ShouldReturnEmpty(ctx context.Context, userID, apiCode string, params map[string]interface{}) bool
// EnrichContext 入参(姓名+身份证)命中白名单时,将命中的 api_codes 写入 context
EnrichContext(ctx context.Context, userID string, params map[string]interface{}) context.Context
InvalidateCache(userID, idCardHash string)
InvalidateAllCache()
}
@@ -24,84 +26,66 @@ type queryWhitelistSnapshot struct {
}
type QueryWhitelistServiceImpl struct {
repo repositories.QueryWhitelistRepository
formConfigService FormConfigService
logger *zap.Logger
repo repositories.QueryWhitelistRepository
logger *zap.Logger
snapshot atomic.Pointer[queryWhitelistSnapshot]
snapshotMu sync.Mutex
// apiCode -> 是否要求身份证入参FormConfig 反射结果,进程内永久缓存)
identityAPICache sync.Map
}
func NewQueryWhitelistService(
repo repositories.QueryWhitelistRepository,
formConfigService FormConfigService,
_ FormConfigService,
logger *zap.Logger,
) QueryWhitelistService {
s := &QueryWhitelistServiceImpl{
repo: repo,
formConfigService: formConfigService,
logger: logger,
repo: repo,
logger: logger,
}
return s
}
// ShouldReturnEmpty 检查是否应返回「查询为空」
// 热路径:入参提取 → API 类型缓存 → 内存快照匹配,不逐请求查库
func (s *QueryWhitelistServiceImpl) ShouldReturnEmpty(
// EnrichContext 判断入参是否命中白名单,并将命中的 api_codes 写入 context不拦截请求
// 热路径:姓名+身份证提取 → 内存快照匹配 → 写入 ctx由各处理器按 api_code 返回查询为空
func (s *QueryWhitelistServiceImpl) EnrichContext(
ctx context.Context,
userID, apiCode string,
userID string,
params map[string]interface{},
) bool {
) context.Context {
identity := ExtractIdentityParams(params)
if !identity.OK {
return false
}
if !s.requiresIdentityInput(ctx, apiCode) {
return false
return ctx
}
idCardHash := HashIDCard(identity.IDCard)
entries, err := s.lookupEntries(ctx, userID, idCardHash)
if err != nil {
s.logger.Error("查询白名单快照失败", zap.Error(err), zap.String("user_id", userID))
return false
return ctx
}
matches := make([]processors.WhitelistMatch, 0, len(entries))
for _, entry := range entries {
if !entry.IsEnabled() {
continue
}
if !entry.MatchesAPICode(apiCode) {
continue
}
if !entry.MatchesName(identity.Name) {
continue
}
s.logger.Info("命中查询白名单",
zap.String("user_id", userID),
zap.String("api_code", apiCode),
zap.String("whitelist_id", entry.ID),
zap.Bool("is_global", entry.IsGlobal()),
zap.Strings("api_codes", entry.APICodes),
)
return true
matches = append(matches, processors.WhitelistMatch{
ID: entry.ID,
APICodes: entry.APICodes,
IsGlobal: entry.IsGlobal(),
})
}
return false
}
func (s *QueryWhitelistServiceImpl) requiresIdentityInput(ctx context.Context, apiCode string) bool {
if s.formConfigService == nil {
return false
}
if cached, ok := s.identityAPICache.Load(apiCode); ok {
return cached.(bool)
}
result := s.formConfigService.RequiresIdentityInput(ctx, apiCode)
s.identityAPICache.Store(apiCode, result)
return result
return processors.WithWhitelistContext(ctx, matches)
}
func (s *QueryWhitelistServiceImpl) lookupEntries(ctx context.Context, userID, idCardHash string) ([]*entities.QueryWhitelistEntry, error) {