From d546ea65025483b0a1c2f9741becd1317dcdb15b Mon Sep 17 00:00:00 2001 From: shanshanzhong Date: Tue, 2 Dec 2025 01:38:32 -0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20=E6=B7=BB=E5=8A=A0=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=BB=91=E5=AE=9A=E5=92=8C=E8=A7=A3=E7=BB=91=E7=9A=84?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在设备绑定和解绑逻辑中添加详细的日志记录,包括用户ID、设备标识符和限制检查 解绑时增加设备管理器的踢出操作,确保设备状态同步 --- internal/logic/auth/bindDeviceLogic.go | 22 +++++ .../logic/public/user/unbindDeviceLogic.go | 85 ++++++++++--------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/internal/logic/auth/bindDeviceLogic.go b/internal/logic/auth/bindDeviceLogic.go index b7fceb1..1995808 100644 --- a/internal/logic/auth/bindDeviceLogic.go +++ b/internal/logic/auth/bindDeviceLogic.go @@ -92,7 +92,18 @@ func (l *BindDeviceLogic) createDeviceForUser(identifier, ip, userAgent string, if limit := l.svcCtx.SessionLimit(); limit > 0 { if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, userId); err == nil { if count >= limit { + l.Infow("device bind blocked by limit", + logger.Field("user_id", userId), + logger.Field("identifier", identifier), + logger.Field("count", count), + logger.Field("limit", limit)) return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。") + } else { + l.Infow("device bind limit check", + logger.Field("user_id", userId), + logger.Field("identifier", identifier), + logger.Field("count", count), + logger.Field("limit", limit)) } } } @@ -158,7 +169,18 @@ func (l *BindDeviceLogic) rebindDeviceToNewUser(deviceInfo *user.Device, ip, use if limit := l.svcCtx.SessionLimit(); limit > 0 { if _, count, err := l.svcCtx.UserModel.QueryDeviceList(l.ctx, newUserId); err == nil { if count >= limit { + l.Infow("device rebind blocked by limit", + logger.Field("new_user_id", newUserId), + logger.Field("identifier", deviceInfo.Identifier), + logger.Field("count", count), + logger.Field("limit", limit)) return xerr.NewErrCodeMsg(xerr.DeviceBindLimitExceeded, "账户绑定设备数已达上限,请移除其他设备后再登录,您也可以再注册一个新账户使用,点击帮助中心查看更多详情。") + } else { + l.Infow("device rebind limit check", + logger.Field("new_user_id", newUserId), + logger.Field("identifier", deviceInfo.Identifier), + logger.Field("count", count), + logger.Field("limit", limit)) } } } diff --git a/internal/logic/public/user/unbindDeviceLogic.go b/internal/logic/public/user/unbindDeviceLogic.go index 3647ca2..3c8d135 100644 --- a/internal/logic/public/user/unbindDeviceLogic.go +++ b/internal/logic/public/user/unbindDeviceLogic.go @@ -35,24 +35,24 @@ func NewUnbindDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Unbi func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error { // 获取当前 token 登录的用户 - u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User) - if !ok { - return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access") - } + u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User) + if !ok { + return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access") + } // 查询解绑设备是否存在 device, err := l.svcCtx.UserModel.FindOneDevice(l.ctx, req.Id) if err != nil { return errors.Wrapf(xerr.NewErrCode(xerr.DeviceNotExist), "find device") } - if device.UserId != u.Id { - return errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "device not belong to user") - } - l.Infow("开始解绑设备", - logger.Field("device_identifier", device.Identifier), - logger.Field("user_id", u.Id)) - start := time.Now() - err = l.svcCtx.DB.Transaction(func(tx *gorm.DB) error { + if device.UserId != u.Id { + return errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "device not belong to user") + } + l.Infow("开始解绑设备", + logger.Field("device_identifier", device.Identifier), + logger.Field("user_id", u.Id)) + start := time.Now() + err = l.svcCtx.DB.Transaction(func(tx *gorm.DB) error { // 1. 查询设备记录 var device user.Device err = tx.Model(&device).Where("id = ?", req.Id).First(&device).Error @@ -83,13 +83,13 @@ func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error { } // 3.2 记录注册日志 - registerLog := log.Register{ - AuthMethod: "device", - Identifier: device.Identifier, - RegisterIP: device.Ip, - UserAgent: device.UserAgent, - Timestamp: time.Now().UnixMilli(), - } + registerLog := log.Register{ + AuthMethod: "device", + Identifier: device.Identifier, + RegisterIP: device.Ip, + UserAgent: device.UserAgent, + Timestamp: time.Now().UnixMilli(), + } content, _ := registerLog.Marshal() if err := tx.Create(&log.SystemLog{ Type: log.TypeRegister.Uint8(), @@ -129,28 +129,29 @@ func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error { } // 6. 清理缓存 - l.Infow("设备解绑并迁移成功", - logger.Field("device_identifier", device.Identifier), - logger.Field("old_user_id", device.UserId), - logger.Field("new_user_id", newUser.Id)) + l.Infow("设备解绑并迁移成功", + logger.Field("device_identifier", device.Identifier), + logger.Field("old_user_id", device.UserId), + logger.Field("new_user_id", newUser.Id)) - return nil - }) - if err != nil { - return err - } - duration := time.Since(start) - identifier := device.Identifier - ctx, cancel := context.WithTimeout(l.ctx, 2*time.Second) - defer cancel() - deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, identifier) - if sessionId, rerr := l.svcCtx.Redis.Get(ctx, deviceCacheKey).Result(); rerr == nil && sessionId != "" { - _ = l.svcCtx.Redis.Del(ctx, deviceCacheKey).Err() - sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId) - _ = l.svcCtx.Redis.Del(ctx, sessionIdCacheKey).Err() - } - l.Infow("设备解绑完成", - logger.Field("device_identifier", identifier), - logger.Field("elapsed_ms", duration.Milliseconds())) - return nil + return nil + }) + if err != nil { + return err + } + duration := time.Since(start) + identifier := device.Identifier + ctx, cancel := context.WithTimeout(l.ctx, 2*time.Second) + defer cancel() + deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, identifier) + if sessionId, rerr := l.svcCtx.Redis.Get(ctx, deviceCacheKey).Result(); rerr == nil && sessionId != "" { + _ = l.svcCtx.Redis.Del(ctx, deviceCacheKey).Err() + sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId) + _ = l.svcCtx.Redis.Del(ctx, sessionIdCacheKey).Err() + } + l.svcCtx.DeviceManager.KickDevice(u.Id, identifier) + l.Infow("设备解绑完成", + logger.Field("device_identifier", identifier), + logger.Field("elapsed_ms", duration.Milliseconds())) + return nil }