邀请
This commit is contained in:
@@ -2,6 +2,7 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -35,6 +36,14 @@ func NewDeviceLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Devic
|
||||
}
|
||||
|
||||
func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *types.LoginResponse, err error) {
|
||||
// 打印请求参数
|
||||
l.Infow("DeviceLogin 请求参数",
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("ip", req.IP),
|
||||
logger.Field("user_agent", req.UserAgent),
|
||||
logger.Field("cf_token", req.CfToken),
|
||||
)
|
||||
|
||||
if !l.svcCtx.Config.Device.Enable {
|
||||
return nil, xerr.NewErrMsg("Device login is disabled")
|
||||
}
|
||||
@@ -97,6 +106,18 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
}
|
||||
}
|
||||
|
||||
// [AuthDebug] Log detailed User Info
|
||||
if userInfo != nil {
|
||||
l.Infow("[AuthDebug] User Info Loaded",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("enable", userInfo.Enable),
|
||||
logger.Field("is_admin", userInfo.IsAdmin),
|
||||
logger.Field("balance", userInfo.Balance),
|
||||
logger.Field("member_status", userInfo.MemberStatus),
|
||||
logger.Field("created_at", userInfo.CreatedAt),
|
||||
)
|
||||
}
|
||||
|
||||
if createdNewDevice {
|
||||
deviceInfo, err = l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||
if err != nil {
|
||||
@@ -118,24 +139,55 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
)
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update device failed: %v", err.Error())
|
||||
}
|
||||
|
||||
// [AuthDebug] Log detailed Device Info
|
||||
l.Infow("[AuthDebug] Device Info",
|
||||
logger.Field("device_id", deviceInfo.Id),
|
||||
logger.Field("identifier", deviceInfo.Identifier),
|
||||
logger.Field("ip", deviceInfo.Ip),
|
||||
logger.Field("enabled", deviceInfo.Enabled),
|
||||
logger.Field("online", deviceInfo.Online),
|
||||
logger.Field("user_agent", deviceInfo.UserAgent),
|
||||
)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
l.Infow("[SESSION_DEBUG] logic start: checking device cache",
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("device_cache_key", deviceCacheKey),
|
||||
)
|
||||
|
||||
if oldSid, getErr := l.svcCtx.Redis.Get(l.ctx, deviceCacheKey).Result(); getErr == nil && oldSid != "" {
|
||||
l.Infow("[SESSION_DEBUG] device cache hit",
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("old_session_id", 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 != "" {
|
||||
l.Infow("[SESSION_DEBUG] session cache hit",
|
||||
logger.Field("old_session_id", oldSid),
|
||||
logger.Field("session_user_id", uidStr),
|
||||
logger.Field("current_user_id", userInfo.Id),
|
||||
)
|
||||
|
||||
// Verify session belongs to current user (防止设备转移后复用其他用户的session)
|
||||
if uidStr == fmt.Sprintf("%d", userInfo.Id) {
|
||||
sessionId = oldSid
|
||||
reuseSession = true
|
||||
// Check TTL
|
||||
ttl, _ := l.svcCtx.Redis.TTL(l.ctx, oldSessionKey).Result()
|
||||
|
||||
l.Infow("reusing existing session for device",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("session_id", sessionId),
|
||||
logger.Field("session_ttl", ttl.Seconds()),
|
||||
)
|
||||
} else {
|
||||
l.Infow("device session belongs to different user, creating new session",
|
||||
@@ -144,7 +196,17 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
logger.Field("identifier", req.Identifier),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
l.Infow("[SESSION_DEBUG] session cache miss or invalid",
|
||||
logger.Field("old_session_id", oldSid),
|
||||
logger.Field("error", existErr),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
l.Infow("[SESSION_DEBUG] device cache miss",
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("error", getErr),
|
||||
)
|
||||
}
|
||||
if !reuseSession {
|
||||
sessionId = uuidx.NewUUID().String()
|
||||
@@ -156,10 +218,21 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
}
|
||||
|
||||
// Generate token (always generate new token, but may reuse sessionId)
|
||||
nowTime := time.Now().Unix()
|
||||
accessExpire := l.svcCtx.Config.JwtAuth.AccessExpire
|
||||
|
||||
l.Infow("[AuthDebug] Generating Token",
|
||||
logger.Field("iat", nowTime),
|
||||
logger.Field("expire_seconds", accessExpire),
|
||||
logger.Field("calculated_exp", nowTime+accessExpire),
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("session_id", sessionId),
|
||||
)
|
||||
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||
nowTime,
|
||||
accessExpire,
|
||||
jwt.WithOption("UserId", userInfo.Id),
|
||||
jwt.WithOption("SessionId", sessionId),
|
||||
jwt.WithOption("LoginType", "device"),
|
||||
@@ -199,6 +272,37 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set device id error: %v", err.Error())
|
||||
}
|
||||
|
||||
// [Debug] Store session detail for troubleshooting
|
||||
// This helps us see "who is online" when multiple devices are logged in.
|
||||
sessionDetail := map[string]interface{}{
|
||||
"session_id": sessionId,
|
||||
"user_id": userInfo.Id,
|
||||
"identifier": req.Identifier,
|
||||
"ip": req.IP,
|
||||
"user_agent": req.UserAgent,
|
||||
"login_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"device_id": deviceInfo.Id,
|
||||
}
|
||||
if detailJson, err := json.Marshal(sessionDetail); err == nil {
|
||||
detailKey := fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sessionId)
|
||||
_ = l.svcCtx.Redis.Set(l.ctx, detailKey, string(detailJson), time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err()
|
||||
}
|
||||
|
||||
// 登录成功 - 打印详细信息用于调试
|
||||
l.Infow("========== 设备登录成功 ==========",
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
logger.Field("identifier", req.Identifier),
|
||||
logger.Field("device_id", deviceInfo.Id),
|
||||
logger.Field("session_id", sessionId),
|
||||
logger.Field("reuse_session", reuseSession),
|
||||
logger.Field("login_type", "device"),
|
||||
logger.Field("login_ip", req.IP),
|
||||
logger.Field("user_agent", req.UserAgent),
|
||||
logger.Field("session_limit", l.svcCtx.SessionLimit()),
|
||||
logger.Field("auth_methods_count", len(userInfo.AuthMethods)),
|
||||
logger.Field("devices_count", len(userInfo.UserDevices)),
|
||||
)
|
||||
|
||||
loginStatus = true
|
||||
return &types.LoginResponse{
|
||||
Token: token,
|
||||
|
||||
Reference in New Issue
Block a user