From 520b126ecf109a7e90597f420531f71936448f5f Mon Sep 17 00:00:00 2001 From: huang Date: Thu, 16 Apr 2026 15:55:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20JWT=20Claims=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=B5=84=E4=BA=A7=E5=AD=97=E6=AE=B5=EF=BC=8C=E7=99=BB=E5=BD=95?= =?UTF-8?q?=20token=20=E6=90=BA=E5=B8=A6=E5=BD=93=E5=89=8D=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- internal/middleware/personal_auth.go | 10 ++++++++++ internal/service/client_auth/service.go | 10 +++++----- pkg/auth/jwt.go | 6 +++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/internal/middleware/personal_auth.go b/internal/middleware/personal_auth.go index bae77b2..a6075e8 100644 --- a/internal/middleware/personal_auth.go +++ b/internal/middleware/personal_auth.go @@ -90,6 +90,8 @@ func (m *PersonalAuthMiddleware) Authenticate() fiber.Handler { c.Locals("customer_id", claims.CustomerID) c.Locals("customer_phone", claims.Phone) + c.Locals("customer_asset_type", claims.AssetType) + c.Locals("customer_asset_id", claims.AssetID) c.Locals("skip_owner_filter", true) m.logger.Debug("个人客户认证成功", @@ -113,3 +115,11 @@ func GetCustomerPhone(c *fiber.Ctx) (string, bool) { phone, ok := c.Locals("customer_phone").(string) return phone, ok } + +// GetCurrentAsset 从 context 中获取当前登录所用的资产类型和 ID +func GetCurrentAsset(c *fiber.Ctx) (assetType string, assetID uint, ok bool) { + assetType, _ = c.Locals("customer_asset_type").(string) + assetID, _ = c.Locals("customer_asset_id").(uint) + ok = assetType != "" && assetID != 0 + return +} diff --git a/internal/service/client_auth/service.go b/internal/service/client_auth/service.go index cfdcc5a..8f401d1 100644 --- a/internal/service/client_auth/service.go +++ b/internal/service/client_auth/service.go @@ -171,7 +171,7 @@ func (s *Service) WechatLogin(ctx context.Context, req *dto.WechatLoginRequest, return nil, err } - token, needBindPhone, err := s.issueLoginToken(ctx, customerID) + token, needBindPhone, err := s.issueLoginToken(ctx, customerID, assetClaims.AssetType, assetClaims.AssetID) if err != nil { return nil, err } @@ -233,7 +233,7 @@ func (s *Service) MiniappLogin(ctx context.Context, req *dto.MiniappLoginRequest return nil, err } - token, needBindPhone, err := s.issueLoginToken(ctx, customerID) + token, needBindPhone, err := s.issueLoginToken(ctx, customerID, assetClaims.AssetType, assetClaims.AssetID) if err != nil { return nil, err } @@ -691,7 +691,7 @@ func (s *Service) markAssetAsSold(ctx context.Context, tx *gorm.DB, assetType st return errors.New(errors.CodeInvalidParam) } -func (s *Service) issueLoginToken(ctx context.Context, customerID uint) (string, bool, error) { +func (s *Service) issueLoginToken(ctx context.Context, customerID uint, assetType string, assetID uint) (string, bool, error) { // 查询用户已绑定的主手机号,写入 JWT,供后续接口直接从 context 取用 var boundPhone string needBindPhone := false @@ -704,7 +704,7 @@ func (s *Service) issueLoginToken(ctx context.Context, customerID uint) (string, needBindPhone = true } - token, err := s.jwtManager.GeneratePersonalCustomerToken(customerID, boundPhone) + token, err := s.jwtManager.GeneratePersonalCustomerToken(customerID, boundPhone, assetType, assetID) if err != nil { return "", false, errors.Wrap(errors.CodeInternalError, err, "生成登录令牌失败") } @@ -762,7 +762,7 @@ func (s *Service) DevLogin(ctx context.Context, identifier string) (string, uint return "", 0, false, err } - token, _, err := s.issueLoginToken(ctx, customerID) + token, _, err := s.issueLoginToken(ctx, customerID, assetType, assetID) if err != nil { return "", 0, false, err } diff --git a/pkg/auth/jwt.go b/pkg/auth/jwt.go index 15cbc1c..b2ab25e 100644 --- a/pkg/auth/jwt.go +++ b/pkg/auth/jwt.go @@ -11,6 +11,8 @@ import ( type PersonalCustomerClaims struct { CustomerID uint `json:"customer_id"` // 个人客户 ID Phone string `json:"phone"` // 手机号 + AssetType string `json:"asset_type"` // 登录所用资产类型(iot_card / device) + AssetID uint `json:"asset_id"` // 登录所用资产 ID jwt.RegisteredClaims } @@ -29,10 +31,12 @@ func NewJWTManager(secretKey string, tokenDuration time.Duration) *JWTManager { } // GeneratePersonalCustomerToken 生成个人客户 Token -func (m *JWTManager) GeneratePersonalCustomerToken(customerID uint, phone string) (string, error) { +func (m *JWTManager) GeneratePersonalCustomerToken(customerID uint, phone string, assetType string, assetID uint) (string, error) { claims := &PersonalCustomerClaims{ CustomerID: customerID, Phone: phone, + AssetType: assetType, + AssetID: assetID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(m.tokenDuration)), IssuedAt: jwt.NewNumericDate(time.Now()),