package middleware import ( "strings" "github.com/break/junhong_cmp_fiber/pkg/auth" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/gofiber/fiber/v2" "go.uber.org/zap" ) // PersonalAuthMiddleware 个人客户认证中间件 type PersonalAuthMiddleware struct { jwtManager *auth.JWTManager logger *zap.Logger } // NewPersonalAuthMiddleware 创建个人客户认证中间件 func NewPersonalAuthMiddleware(jwtManager *auth.JWTManager, logger *zap.Logger) *PersonalAuthMiddleware { return &PersonalAuthMiddleware{ jwtManager: jwtManager, logger: logger, } } // Authenticate 认证中间件 func (m *PersonalAuthMiddleware) Authenticate() fiber.Handler { return func(c *fiber.Ctx) error { // 从 Authorization header 获取 token authHeader := c.Get("Authorization") if authHeader == "" { m.logger.Warn("个人客户认证失败:缺少 Authorization header", zap.String("path", c.Path()), zap.String("method", c.Method()), ) return errors.New(errors.CodeUnauthorized, "未提供认证令牌") } // 检查 Bearer 前缀 parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { m.logger.Warn("个人客户认证失败:Authorization header 格式错误", zap.String("path", c.Path()), zap.String("auth_header", authHeader), ) return errors.New(errors.CodeUnauthorized, "认证令牌格式错误") } token := parts[1] // 验证 token claims, err := m.jwtManager.VerifyPersonalCustomerToken(token) if err != nil { m.logger.Warn("个人客户认证失败:token 验证失败", zap.String("path", c.Path()), zap.Error(err), ) return errors.New(errors.CodeUnauthorized, "认证令牌无效或已过期") } // 将客户信息存储到 context 中 c.Locals("customer_id", claims.CustomerID) c.Locals("customer_phone", claims.Phone) // 设置 SkipOwnerFilter 标记,跳过 B 端数据权限过滤 // 个人客户不参与 RBAC 权限体系,不需要 Owner 过滤 c.Locals("skip_owner_filter", true) m.logger.Debug("个人客户认证成功", zap.Uint("customer_id", claims.CustomerID), zap.String("phone", claims.Phone), zap.String("path", c.Path()), ) return c.Next() } } // GetCustomerID 从 context 中获取当前个人客户 ID func GetCustomerID(c *fiber.Ctx) (uint, bool) { customerID, ok := c.Locals("customer_id").(uint) return customerID, ok } // GetCustomerPhone 从 context 中获取当前个人客户手机号 func GetCustomerPhone(c *fiber.Ctx) (string, bool) { phone, ok := c.Locals("customer_phone").(string) return phone, ok }