fix: 系统性修复安全问题、性能问题和错误处理

安全问题修复:
- X-Forwarded-For越界检查(auth.go)
- checkTokenStatus Context参数传递(auth.go)
- Type Assertion安全检查(auth.go)

性能问题修复:
- TokenCache过期清理机制
- BruteForceProtection过期清理
- InMemoryIdempotencyStore过期清理

错误处理修复:
- AuditStore.Emit返回error
- domain层emitAudit辅助方法
- List方法返回空slice而非nil
- 金额/价格负数验证

架构一致性:
- 统一使用model.RoleHierarchyLevels

新增功能:
- Alert API完整实现(CRUD+Resolve)
- pkg/error错误码集中管理
This commit is contained in:
Your Name
2026-04-07 07:41:25 +08:00
parent 12ce4913cd
commit d5b5a8ece0
21 changed files with 2321 additions and 83 deletions

View File

@@ -6,6 +6,7 @@ import (
"log"
"net/http"
"lijiaoqiao/supply-api/internal/iam/model"
"lijiaoqiao/supply-api/internal/middleware"
)
@@ -17,7 +18,12 @@ const (
IAMTokenClaimsKey iamContextKey = "iam_token_claims"
)
// ClaimsVersion Token Claims版本号用于迁移追踪
const ClaimsVersion = 1
// IAMTokenClaims IAM扩展Token Claims
// 版本: v1
// 迁移路径: 见 MigrateClaims 函数
type IAMTokenClaims struct {
SubjectID string `json:"subject_id"`
Role string `json:"role"`
@@ -25,30 +31,73 @@ type IAMTokenClaims struct {
TenantID int64 `json:"tenant_id"`
UserType string `json:"user_type"` // 用户类型: platform/supply/consumer
Permissions []string `json:"permissions"` // 细粒度权限列表
// 版本控制字段(未来迁移用)
Version int `json:"version,omitempty"`
}
// 角色层级定义
var roleHierarchyLevels = map[string]int{
"super_admin": 100,
"org_admin": 50,
"supply_admin": 40,
"consumer_admin": 40,
"operator": 30,
"developer": 20,
"finops": 20,
"supply_operator": 30,
"supply_finops": 20,
"supply_viewer": 10,
"consumer_operator": 30,
"consumer_viewer": 10,
"viewer": 10,
// MigrateClaims 将旧版本Claims迁移到当前版本
// 迁移路径:
// v0 -> v1: 初始版本,添加 Version 字段
//
// 使用示例:
// claims := &IAMTokenClaims{}
// if err := json.Unmarshal(data, claims); err != nil {
// return err
// }
// migrated := MigrateClaims(claims)
// // 使用 migrated
func MigrateClaims(claims *IAMTokenClaims) *IAMTokenClaims {
if claims == nil {
return nil
}
// 当前版本是v1无需迁移
// 未来版本迁移:
// case 0:
// claims = migrateV0ToV1(claims)
// case 1:
// claims = migrateV1ToV2(claims)
claims.Version = ClaimsVersion
return claims
}
// ValidateClaims 验证Claims完整性
func ValidateClaims(claims *IAMTokenClaims) error {
if claims == nil {
return ErrInvalidClaims
}
if claims.SubjectID == "" {
return ErrInvalidSubjectID
}
return nil
}
// 迁移相关错误
var (
ErrInvalidClaims = &ClaimsError{Code: "IAM_CLAIMS_4001", Message: "invalid claims structure"}
ErrInvalidSubjectID = &ClaimsError{Code: "IAM_CLAIMS_4002", Message: "subject_id is required"}
)
// ClaimsError Claims相关错误
type ClaimsError struct {
Code string
Message string
}
func (e *ClaimsError) Error() string {
return e.Code + ": " + e.Message
}
// 角色层级定义(已废弃,请使用 model.RoleHierarchyLevels
// @deprecated 使用 model.RoleHierarchyLevels 获取角色层级
var roleHierarchyLevels = model.RoleHierarchyLevels
// ScopeAuthMiddleware Scope权限验证中间件
type ScopeAuthMiddleware struct {
// 路由-Scope映射
routeScopePolicies map[string][]string
// 角色层级已废弃使用包级变量roleHierarchyLevels
// 角色层级
roleHierarchy map[string]int
}
@@ -56,7 +105,7 @@ type ScopeAuthMiddleware struct {
func NewScopeAuthMiddleware() *ScopeAuthMiddleware {
return &ScopeAuthMiddleware{
routeScopePolicies: make(map[string][]string),
roleHierarchy: roleHierarchyLevels,
roleHierarchy: model.RoleHierarchyLevels, // 使用统一的角色层级定义
}
}
@@ -142,11 +191,9 @@ func HasRoleLevel(ctx context.Context, minLevel int) bool {
}
// GetRoleLevel 获取角色层级数值
// @deprecated 请使用 model.GetRoleLevelByCode
func GetRoleLevel(role string) int {
if level, ok := roleHierarchyLevels[role]; ok {
return level
}
return 0
return model.GetRoleLevelByCode(role)
}
// GetIAMTokenClaims 获取IAM Token Claims

View File

@@ -15,6 +15,7 @@ const (
)
// 角色层级常量(用于权限优先级判断)
// 注意:这些常量值必须与 RoleHierarchyLevels map保持一致
const (
LevelSuperAdmin = 100
LevelOrgAdmin = 50
@@ -25,6 +26,33 @@ const (
LevelViewer = 10
)
// RoleHierarchyLevels 角色层级映射(用于权限验证)
// 层级越高权限越大。superset角色可以执行subset角色的操作。
// 注意此map的值必须与上述常量保持一致
var RoleHierarchyLevels = map[string]int{
"super_admin": LevelSuperAdmin, // 100 - 超级管理员
"org_admin": LevelOrgAdmin, // 50 - 组织管理员
"supply_admin": LevelSupplyAdmin, // 40 - 供应商管理员
"consumer_admin": LevelSupplyAdmin, // 40 - 消费者管理员(同供应商)
"operator": LevelOperator, // 30 - 操作员
"developer": LevelDeveloper, // 20 - 开发者
"finops": LevelFinops, // 20 - 财务运营
"supply_operator": LevelOperator, // 30 - 供应商操作员
"supply_finops": LevelFinops, // 20 - 供应商财务
"supply_viewer": LevelViewer, // 10 - 供应商查看者
"consumer_operator": LevelOperator, // 30 - 消费者操作员
"consumer_viewer": LevelViewer, // 10 - 消费者查看者
"viewer": LevelViewer, // 10 - 通用查看者
}
// GetRoleLevelByCode 根据角色代码获取层级数值
func GetRoleLevelByCode(roleCode string) int {
if level, ok := RoleHierarchyLevels[roleCode]; ok {
return level
}
return 0 // 默认最低级别
}
// 角色错误定义
var (
ErrInvalidRoleCode = errors.New("invalid role code: cannot be empty")