This commit is contained in:
@@ -120,10 +120,42 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
}
|
||||
}
|
||||
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Check if device has an existing valid session - reuse it instead of creating new one
|
||||
var sessionId string
|
||||
var reuseSession bool
|
||||
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, deviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
// Check if old session is still valid AND belongs to current user
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, existErr := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); existErr == nil && uidStr != "" {
|
||||
// Verify session belongs to current user (防止设备转移后复用其他用户的session)
|
||||
if uidStr == fmt.Sprintf("%d", userInfo.Id) {
|
||||
sessionId = oldSid
|
||||
reuseSession = true
|
||||
l.Infow("reusing existing session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
} else {
|
||||
l.Infow("device session belongs to different user, creating new session",
|
||||
logger.Field("current_user_id", userInfo.Id),
|
||||
logger.Field("session_user_id", uidStr),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !reuseSession {
|
||||
sessionId = uuidx.NewUUID().String()
|
||||
l.Infow("creating new session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
}
|
||||
|
||||
// Generate token
|
||||
// Generate token (always generate new token, but may reuse sessionId)
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
@@ -141,23 +173,14 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
|
||||
// If device had a previous session, invalidate it first (MUST be before EnforceUserSessionLimit)
|
||||
oldDeviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, oldDeviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, _ := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); uidStr != "" {
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldSessionKey).Err()
|
||||
sessionsKey := fmt.Sprintf("%s%v", config.UserSessionsKeyPrefix, uidStr)
|
||||
_ = l.svcCtx.Redis.ZRem(l.ctx, sessionsKey, oldSid).Err()
|
||||
// Only enforce session limit and add to user sessions if this is a new session
|
||||
if !reuseSession {
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldDeviceCacheKey).Err()
|
||||
}
|
||||
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
|
||||
// Store session id in redis
|
||||
// Store/refresh session id in redis (extend TTL)
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
l.Errorw("set session id error",
|
||||
@@ -167,8 +190,7 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
// Store device id in redis
|
||||
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
// Store/refresh device-to-session mapping (extend TTL)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, deviceCacheKey, sessionId, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
l.Errorw("set device id error",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
|
||||
@@ -220,7 +220,40 @@ func (l *EmailLoginLogic) EmailLogin(req *types.EmailLoginRequest) (resp *types.
|
||||
req.LoginType = l.ctx.Value(constant.LoginType).(string)
|
||||
}
|
||||
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Check if device has an existing valid session - reuse it instead of creating new one
|
||||
var sessionId string
|
||||
var reuseSession bool
|
||||
var deviceCacheKey string
|
||||
if req.Identifier != "" {
|
||||
deviceCacheKey = fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, deviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
// Check if old session is still valid AND belongs to current user
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, existErr := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); existErr == nil && uidStr != "" {
|
||||
// Verify session belongs to current user (防止设备转移后复用其他用户的session)
|
||||
if uidStr == fmt.Sprintf("%d", userInfo.Id) {
|
||||
sessionId = oldSid
|
||||
reuseSession = true
|
||||
l.Infow("reusing existing session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
} else {
|
||||
l.Infow("device session belongs to different user, creating new session",
|
||||
logger.Field("current_user_id", userInfo.Id),
|
||||
logger.Field("session_user_id", uidStr),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !reuseSession {
|
||||
sessionId = uuidx.NewUUID().String()
|
||||
}
|
||||
|
||||
// Generate token (always generate new token, but may reuse sessionId)
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
@@ -233,32 +266,22 @@ func (l *EmailLoginLogic) EmailLogin(req *types.EmailLoginRequest) (resp *types.
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
// If device had a previous session, invalidate it first (MUST be before EnforceUserSessionLimit)
|
||||
if req.Identifier != "" {
|
||||
oldDeviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, oldDeviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, _ := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); uidStr != "" {
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldSessionKey).Err()
|
||||
sessionsKey := fmt.Sprintf("%s%v", config.UserSessionsKeyPrefix, uidStr)
|
||||
_ = l.svcCtx.Redis.ZRem(l.ctx, sessionsKey, oldSid).Err()
|
||||
}
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldDeviceCacheKey).Err()
|
||||
|
||||
// Only enforce session limit and add to user sessions if this is a new session
|
||||
if !reuseSession {
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
// Store/refresh session id in redis (extend TTL)
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
// Store device-to-session mapping
|
||||
// Store/refresh device-to-session mapping (extend TTL)
|
||||
if req.Identifier != "" {
|
||||
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
_ = l.svcCtx.Redis.Set(l.ctx, deviceCacheKey, sessionId, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err()
|
||||
}
|
||||
|
||||
|
||||
@@ -144,9 +144,40 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
|
||||
req.LoginType = l.ctx.Value(constant.LoginType).(string)
|
||||
}
|
||||
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Generate token
|
||||
// Check if device has an existing valid session - reuse it instead of creating new one
|
||||
var sessionId string
|
||||
var reuseSession bool
|
||||
var deviceCacheKey string
|
||||
if req.Identifier != "" {
|
||||
deviceCacheKey = fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, deviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
// Check if old session is still valid AND belongs to current user
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, existErr := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); existErr == nil && uidStr != "" {
|
||||
// Verify session belongs to current user (防止设备转移后复用其他用户的session)
|
||||
if uidStr == fmt.Sprintf("%d", userInfo.Id) {
|
||||
sessionId = oldSid
|
||||
reuseSession = true
|
||||
l.Infow("reusing existing session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
} else {
|
||||
l.Infow("device session belongs to different user, creating new session",
|
||||
logger.Field("current_user_id", userInfo.Id),
|
||||
logger.Field("session_user_id", uidStr),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !reuseSession {
|
||||
sessionId = uuidx.NewUUID().String()
|
||||
}
|
||||
|
||||
// Generate token (always generate new token, but may reuse sessionId)
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
@@ -159,13 +190,24 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
|
||||
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
|
||||
// Only enforce session limit and add to user sessions if this is a new session
|
||||
if !reuseSession {
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Store/refresh session id in redis (extend TTL)
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
// Store/refresh device-to-session mapping (extend TTL)
|
||||
if req.Identifier != "" {
|
||||
_ = l.svcCtx.Redis.Set(l.ctx, deviceCacheKey, sessionId, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err()
|
||||
}
|
||||
loginStatus = true
|
||||
return &types.LoginResponse{
|
||||
Token: token,
|
||||
|
||||
@@ -115,9 +115,41 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
|
||||
if l.ctx.Value(constant.LoginType) != nil {
|
||||
req.LoginType = l.ctx.Value(constant.LoginType).(string)
|
||||
}
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Generate token
|
||||
|
||||
// Check if device has an existing valid session - reuse it instead of creating new one
|
||||
var sessionId string
|
||||
var reuseSession bool
|
||||
var deviceCacheKey string
|
||||
if req.Identifier != "" {
|
||||
deviceCacheKey = fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, deviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
// Check if old session is still valid AND belongs to current user
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, existErr := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); existErr == nil && uidStr != "" {
|
||||
// Verify session belongs to current user (防止设备转移后复用其他用户的session)
|
||||
if uidStr == fmt.Sprintf("%d", userInfo.Id) {
|
||||
sessionId = oldSid
|
||||
reuseSession = true
|
||||
l.Infow("reusing existing session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
} else {
|
||||
l.Infow("device session belongs to different user, creating new session",
|
||||
logger.Field("current_user_id", userInfo.Id),
|
||||
logger.Field("session_user_id", uidStr),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !reuseSession {
|
||||
sessionId = uuidx.NewUUID().String()
|
||||
}
|
||||
|
||||
// Generate token (always generate new token, but may reuse sessionId)
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
@@ -131,32 +163,22 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
|
||||
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
// If device had a previous session, invalidate it first (MUST be before EnforceUserSessionLimit)
|
||||
if req.Identifier != "" {
|
||||
oldDeviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, oldDeviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
oldSessionKey := fmt.Sprintf("%v:%v", config.SessionIdKey, oldSid)
|
||||
if uidStr, _ := l.svcCtx.Redis.Get(l.ctx, oldSessionKey).Result(); uidStr != "" {
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldSessionKey).Err()
|
||||
sessionsKey := fmt.Sprintf("%s%v", config.UserSessionsKeyPrefix, uidStr)
|
||||
_ = l.svcCtx.Redis.ZRem(l.ctx, sessionsKey, oldSid).Err()
|
||||
}
|
||||
_ = l.svcCtx.Redis.Del(l.ctx, oldDeviceCacheKey).Err()
|
||||
|
||||
// Only enforce session limit and add to user sessions if this is a new session
|
||||
if !reuseSession {
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err = l.svcCtx.EnforceUserSessionLimit(l.ctx, userInfo.Id, sessionId, l.svcCtx.SessionLimit()); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "enforce session limit error: %v", err.Error())
|
||||
}
|
||||
// Store/refresh session id in redis (extend TTL)
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
// Store device-to-session mapping
|
||||
// Store/refresh device-to-session mapping (extend TTL)
|
||||
if req.Identifier != "" {
|
||||
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, req.Identifier)
|
||||
_ = l.svcCtx.Redis.Set(l.ctx, deviceCacheKey, sessionId, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user