实现个人客户微信认证和短信验证功能
- 添加个人客户微信登录和手机验证码登录接口 - 实现个人客户设备、ICCID、手机号关联管理 - 添加短信发送服务(HTTP 客户端) - 添加微信认证服务(含 mock 实现) - 添加 JWT Token 生成和验证工具 - 创建数据库迁移脚本(personal_customer 关联表) - 修复测试文件中的路由注册参数错误 - 重构 scripts 目录结构(分离独立脚本到子目录) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
89
internal/middleware/personal_auth.go
Normal file
89
internal/middleware/personal_auth.go
Normal file
@@ -0,0 +1,89 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user