fix(P2): 修复4个P2轻微问题

P2-01: 通配符scope安全风险 (scope_auth.go)
- 添加hasWildcardScope()函数检测通配符scope
- 添加logWildcardScopeAccess()函数记录审计日志
- 在RequireScope/RequireAllScopes/RequireAnyScope中间件中调用审计日志

P2-02: isSamePayload比较字段不完整 (audit_service.go)
- 添加ActionDetail字段比较
- 添加ResultMessage字段比较
- 添加Extensions字段比较
- 添加compareExtensions()辅助函数

P2-03: regexp.MustCompile可能panic (sanitizer.go)
- 添加compileRegex()安全编译函数替代MustCompile
- 处理编译错误,避免panic

P2-04: StrategyRoundRobin未实现 (router.go)
- 添加selectByRoundRobin()方法
- 添加roundRobinCounter原子计数器
- 使用atomic.AddUint64实现线程安全的轮询

P2-05: 错误信息泄露内部细节 - 已在MED-09中处理,跳过
This commit is contained in:
Your Name
2026-04-03 09:39:32 +08:00
parent 732c97f85b
commit b2d32be14f
8 changed files with 289 additions and 19 deletions

View File

@@ -3,6 +3,7 @@ package middleware
import (
"context"
"encoding/json"
"log"
"net/http"
"lijiaoqiao/supply-api/internal/middleware"
@@ -174,6 +175,31 @@ func hasScope(scopes []string, target string) bool {
return false
}
// hasWildcardScope 检查scope列表是否包含通配符scope
func hasWildcardScope(scopes []string) bool {
for _, scope := range scopes {
if scope == "*" {
return true
}
}
return false
}
// logWildcardScopeAccess 记录通配符scope访问的审计日志
// P2-01: 通配符scope是安全风险应记录审计日志
func logWildcardScopeAccess(ctx context.Context, claims *IAMTokenClaims, requiredScope string) {
if claims == nil {
return
}
// 检查是否使用了通配符scope
if hasWildcardScope(claims.Scope) {
// 记录审计日志
log.Printf("[AUDIT] P2-01 WILDCARD_SCOPE_ACCESS: subject_id=%s, role=%s, required_scope=%s, tenant_id=%d, user_type=%s",
claims.SubjectID, claims.Role, requiredScope, claims.TenantID, claims.UserType)
}
}
// RequireScope 返回一个要求特定Scope的中间件
func (m *ScopeAuthMiddleware) RequireScope(requiredScope string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
@@ -193,6 +219,11 @@ func (m *ScopeAuthMiddleware) RequireScope(requiredScope string) func(http.Handl
return
}
// P2-01: 记录通配符scope访问的审计日志
if hasWildcardScope(claims.Scope) {
logWildcardScopeAccess(r.Context(), claims, requiredScope)
}
next.ServeHTTP(w, r)
})
}
@@ -218,6 +249,11 @@ func (m *ScopeAuthMiddleware) RequireAllScopes(requiredScopes []string) func(htt
}
}
// P2-01: 记录通配符scope访问的审计日志
if hasWildcardScope(claims.Scope) {
logWildcardScopeAccess(r.Context(), claims, "")
}
next.ServeHTTP(w, r)
})
}
@@ -242,6 +278,11 @@ func (m *ScopeAuthMiddleware) RequireAnyScope(requiredScopes []string) func(http
return
}
// P2-01: 记录通配符scope访问的审计日志
if hasWildcardScope(claims.Scope) {
logWildcardScopeAccess(r.Context(), claims, "")
}
next.ServeHTTP(w, r)
})
}

View File

@@ -569,3 +569,28 @@ func TestMED01_RequireAnyScope_EmptyScopesShouldDenyAccess(t *testing.T) {
// assert - 空scope列表应该拒绝访问安全修复
assert.Equal(t, http.StatusForbidden, rec.Code, "empty required scopes should DENY access (security fix)")
}
// P2-01: scope=="*"时直接返回true应记录审计日志
// 由于hasScope是内部函数我们通过中间件来验证通配符scope的行为
func TestP2_01_WildcardScope_SecurityRisk(t *testing.T) {
// 创建一个带通配符scope的claims
claims := &IAMTokenClaims{
SubjectID: "user:p2-01",
Role: "super_admin",
Scope: []string{"*"}, // 通配符scope代表所有权限
TenantID: 1,
}
ctx := WithIAMClaims(context.Background(), claims)
// 通配符scope应该能通过任何scope检查
assert.True(t, CheckScope(ctx, "platform:read"), "wildcard scope should have platform:read")
assert.True(t, CheckScope(ctx, "platform:write"), "wildcard scope should have platform:write")
assert.True(t, CheckScope(ctx, "any:custom:scope"), "wildcard scope should have any:custom:scope")
// 问题通配符scope被使用时没有记录审计日志
// 修复建议在hasScope返回true时如果scope是"*",应该记录审计日志
// 这是一个安全风险,因为无法追踪何时使用了超级权限
t.Logf("P2-01: Wildcard scope usage should be audited for security compliance")
}