移除login直连数据库,将数据库操作交给db服处理
This commit is contained in:
parent
a2ecd518aa
commit
78283ada73
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
AccountNormal = 1 // 正常
|
||||
//AccountNormal = 1 // 正常
|
||||
AccountFrozen = 2 // 冻结
|
||||
AccountBanned = 3 // 封禁
|
||||
)
|
||||
@ -33,7 +33,7 @@ func (u UserAccount) GetId() uint {
|
||||
// 玩家登录记录表
|
||||
type UserLoginLog struct {
|
||||
gorm.Model
|
||||
PlayerID uint `gorm:"index"` // 关联玩家ID
|
||||
UID uint `gorm:"index"` // 关联玩家ID
|
||||
LoginIP string `gorm:"type:varchar(45);not null"` // 登录IP
|
||||
LoginTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 登录时间
|
||||
DeviceInfo string `gorm:"type:varchar(255)"` // 设备信息(JSON格式)
|
||||
|
@ -10,7 +10,8 @@ enum ErrCode
|
||||
LoginUserOrPwdErr = 102; // 帐号或密码错误
|
||||
AccountFrozen = 103; // 帐号已冻结
|
||||
AccountBanned = 104; // 帐号已封禁
|
||||
RegisterUserExist = 120; // 已有该帐号,无法注册
|
||||
RegisterUserExist = 110; // 已有该帐号,无法注册
|
||||
VersionTooLow = 115; // 版本太低,无法登陆
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@ enum ServiceTypeId
|
||||
STI_Gate = 100; // 网关id
|
||||
STI_Login = 101; // 登陆服
|
||||
STI_Chat = 102; // 聊天服
|
||||
STI_DB = 103; // db服
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,7 +30,8 @@ const (
|
||||
ErrCode_LoginUserOrPwdErr ErrCode = 102 // 帐号或密码错误
|
||||
ErrCode_AccountFrozen ErrCode = 103 // 帐号已冻结
|
||||
ErrCode_AccountBanned ErrCode = 104 // 帐号已封禁
|
||||
ErrCode_RegisterUserExist ErrCode = 120 // 已有该帐号,无法注册
|
||||
ErrCode_RegisterUserExist ErrCode = 110 // 已有该帐号,无法注册
|
||||
ErrCode_VersionTooLow ErrCode = 115 // 版本太低,无法登陆
|
||||
)
|
||||
|
||||
// Enum value maps for ErrCode.
|
||||
@ -42,7 +43,8 @@ var (
|
||||
102: "LoginUserOrPwdErr",
|
||||
103: "AccountFrozen",
|
||||
104: "AccountBanned",
|
||||
120: "RegisterUserExist",
|
||||
110: "RegisterUserExist",
|
||||
115: "VersionTooLow",
|
||||
}
|
||||
ErrCode_value = map[string]int32{
|
||||
"OK": 0,
|
||||
@ -51,7 +53,8 @@ var (
|
||||
"LoginUserOrPwdErr": 102,
|
||||
"AccountFrozen": 103,
|
||||
"AccountBanned": 104,
|
||||
"RegisterUserExist": 120,
|
||||
"RegisterUserExist": 110,
|
||||
"VersionTooLow": 115,
|
||||
}
|
||||
)
|
||||
|
||||
@ -87,7 +90,7 @@ var File_code_proto protoreflect.FileDescriptor
|
||||
const file_code_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"code.proto\x12\x02pb*\x86\x01\n" +
|
||||
"code.proto\x12\x02pb*\x99\x01\n" +
|
||||
"\aErrCode\x12\x06\n" +
|
||||
"\x02OK\x10\x00\x12\r\n" +
|
||||
"\tSystemErr\x10\x01\x12\x10\n" +
|
||||
@ -95,7 +98,8 @@ const file_code_proto_rawDesc = "" +
|
||||
"\x11LoginUserOrPwdErr\x10f\x12\x11\n" +
|
||||
"\rAccountFrozen\x10g\x12\x11\n" +
|
||||
"\rAccountBanned\x10h\x12\x15\n" +
|
||||
"\x11RegisterUserExist\x10xB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
"\x11RegisterUserExist\x10n\x12\x11\n" +
|
||||
"\rVersionTooLow\x10sB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
|
||||
var (
|
||||
file_code_proto_rawDescOnce sync.Once
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
// 命名规则:
|
||||
// 1. 所有游戏id都在msgId.proto的MsgId中定义,前缀需有C2S,S2C,Ntf三种之一,后缀统一为Id
|
||||
// 1. 所有消息id都在msgId.proto的MsgId中定义,前缀需有C2S,S2C,Ntf三种之一,后缀统一为Id
|
||||
// 2. 所有错误码都在code.proto的ErrCode中定义
|
||||
// 3. 所有消息名为对应消息id去掉后缀Id组成
|
||||
type MsgId int32
|
||||
|
@ -28,6 +28,7 @@ const (
|
||||
ServiceTypeId_STI_Gate ServiceTypeId = 100 // 网关id
|
||||
ServiceTypeId_STI_Login ServiceTypeId = 101 // 登陆服
|
||||
ServiceTypeId_STI_Chat ServiceTypeId = 102 // 聊天服
|
||||
ServiceTypeId_STI_DB ServiceTypeId = 103 // db服
|
||||
)
|
||||
|
||||
// Enum value maps for ServiceTypeId.
|
||||
@ -37,12 +38,14 @@ var (
|
||||
100: "STI_Gate",
|
||||
101: "STI_Login",
|
||||
102: "STI_Chat",
|
||||
103: "STI_DB",
|
||||
}
|
||||
ServiceTypeId_value = map[string]int32{
|
||||
"STI_Unknown": 0,
|
||||
"STI_Gate": 100,
|
||||
"STI_Login": 101,
|
||||
"STI_Chat": 102,
|
||||
"STI_DB": 103,
|
||||
}
|
||||
)
|
||||
|
||||
@ -77,12 +80,14 @@ var File_service_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_service_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\rservice.proto\x12\x02pb*K\n" +
|
||||
"\rservice.proto\x12\x02pb*W\n" +
|
||||
"\rServiceTypeId\x12\x0f\n" +
|
||||
"\vSTI_Unknown\x10\x00\x12\f\n" +
|
||||
"\bSTI_Gate\x10d\x12\r\n" +
|
||||
"\tSTI_Login\x10e\x12\f\n" +
|
||||
"\bSTI_Chat\x10fB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
"\bSTI_Chat\x10f\x12\n" +
|
||||
"\n" +
|
||||
"\x06STI_DB\x10gB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||
|
||||
var (
|
||||
file_service_proto_rawDescOnce sync.Once
|
||||
|
8
common/rpcName/rpcName.go
Normal file
8
common/rpcName/rpcName.go
Normal file
@ -0,0 +1,8 @@
|
||||
package rpcName
|
||||
|
||||
const (
|
||||
GetUserAccount = "get.user.account.rpc"
|
||||
CreateUserAccount = "create.user.account.rpc"
|
||||
UpdateUserPassword = "update.user.password.rpc"
|
||||
LogUserAccountLogin = "user.login.rpc"
|
||||
)
|
@ -1,7 +0,0 @@
|
||||
package rpcName
|
||||
|
||||
const (
|
||||
GetUserAccount = "get.user.account.rpc"
|
||||
CreateUserAccount = "create.user.account.rpc"
|
||||
UpdateUserPassword = "update.user.password.rpc"
|
||||
)
|
@ -4,4 +4,5 @@ const (
|
||||
Gate = "gate"
|
||||
Chat = "chat"
|
||||
Login = "login"
|
||||
Db = "db"
|
||||
)
|
||||
|
23
common/utils/redis.go
Normal file
23
common/utils/redis.go
Normal file
@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/fox/fox/ksync"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 动态调整redis池
|
||||
func AutoSetRedisPool(rdb *redis.Client) {
|
||||
// 连接池自动扩展
|
||||
ksync.GoSafe(func() {
|
||||
for {
|
||||
stats := rdb.PoolStats()
|
||||
usage := float64(stats.TotalConns-stats.IdleConns) / float64(stats.TotalConns)
|
||||
if usage > 0.8 { // 使用率超过80%
|
||||
// 动态调整PoolSize
|
||||
rdb.Options().PoolSize = int(float64(rdb.Options().PoolSize) * 1.2)
|
||||
}
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
}, nil)
|
||||
}
|
8
common/utils/util.go
Normal file
8
common/utils/util.go
Normal file
@ -0,0 +1,8 @@
|
||||
package utils
|
||||
|
||||
func Tie[T any](ret bool, v1, v2 T) T {
|
||||
if ret {
|
||||
return v1
|
||||
}
|
||||
return v2
|
||||
}
|
@ -2,6 +2,7 @@ package operation
|
||||
|
||||
import (
|
||||
"game/common/model/user"
|
||||
"game/common/utils"
|
||||
"game/server/db/config"
|
||||
"github.com/fox/fox/db"
|
||||
"github.com/fox/fox/log"
|
||||
@ -25,11 +26,13 @@ func InitRedis() {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
utils.AutoSetRedisPool(UserRedis)
|
||||
AccountRedis, err = db.InitRedis(cfg.Password, cfg.Host, cfg.Port, 1)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
utils.AutoSetRedisPool(AccountRedis)
|
||||
}
|
||||
|
||||
func InitDb() {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"game/common/model"
|
||||
"game/common/model/user"
|
||||
"game/common/proto/pb"
|
||||
"game/common/serialization"
|
||||
"game/common/utils"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/go-redis/redis/v8"
|
||||
@ -15,6 +16,7 @@ import (
|
||||
)
|
||||
|
||||
type UserAccountOp struct {
|
||||
logDb *gorm.DB
|
||||
db *gorm.DB
|
||||
accountRedis *redis.Client
|
||||
accountOp *model.TableOp[user.UserAccount]
|
||||
@ -22,6 +24,7 @@ type UserAccountOp struct {
|
||||
|
||||
func NewUserAccountOp() *UserAccountOp {
|
||||
return &UserAccountOp{
|
||||
logDb: LogDB,
|
||||
db: UserDB,
|
||||
accountRedis: AccountRedis,
|
||||
accountOp: model.NewTableOp[user.UserAccount](UserDB, AccountRedis),
|
||||
@ -36,12 +39,18 @@ func (s *UserAccountOp) GetUserAccount(username string) (*user.UserAccount, pb.E
|
||||
sUid, err := s.accountRedis.Get(context.Background(), s.redisKey(username)).Result()
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
var us user.UserAccount
|
||||
err = s.db.Where("username = ?", username).First(&us).Error
|
||||
us := &user.UserAccount{}
|
||||
err = s.db.Where("username = ?", username).First(us).Error
|
||||
if err != nil {
|
||||
log.ErrorF("find user:%v err:%v", username, err)
|
||||
return nil, pb.ErrCode_SystemErr
|
||||
}
|
||||
// 从db中查到后写入redis,并建立索引
|
||||
if us.Username != "" && us.ID > 0 {
|
||||
_, _ = s.accountOp.Update(us.ID, serialization.StructToMap(us))
|
||||
_ = s.accountRedis.Set(context.Background(), s.redisKey(username), us.ID, model.TableExpire).Err()
|
||||
}
|
||||
return us, pb.ErrCode_OK
|
||||
} else {
|
||||
log.ErrorF("find user:%v err:%v", username, err)
|
||||
return nil, pb.ErrCode_SystemErr
|
||||
@ -69,7 +78,8 @@ func (s *UserAccountOp) CreateUserAccount(us *user.UserAccount) (*user.UserAccou
|
||||
if code != pb.ErrCode_OK {
|
||||
return nil, code
|
||||
}
|
||||
s.accountRedis.Set(context.Background(), s.redisKey(us.Username), us.ID, model.TableExpire)
|
||||
// 建立索引
|
||||
_ = s.accountRedis.Set(context.Background(), s.redisKey(us.Username), us.ID, model.TableExpire).Err()
|
||||
return us, pb.ErrCode_OK
|
||||
}
|
||||
|
||||
@ -84,25 +94,18 @@ func (s *UserAccountOp) UpdateUserPassword(us *user.UserAccount) (*user.UserAcco
|
||||
var code pb.ErrCode
|
||||
us, code = s.accountOp.Update(us.ID, map[string]any{"password": hashedPassword})
|
||||
if code != pb.ErrCode_OK {
|
||||
s.accountRedis.Expire(context.Background(), s.redisKey(us.Username), model.TableExpire)
|
||||
_ = s.accountRedis.Expire(context.Background(), s.redisKey(us.Username), model.TableExpire).Err()
|
||||
}
|
||||
return us, code
|
||||
}
|
||||
|
||||
//// 记录登录日志
|
||||
//func (s *UserAccountOp) recordLoginLog(userID uint, ip, deviceID string, success bool, failReason string) {
|
||||
// logEntry := user.UserLoginLog{
|
||||
// PlayerID: userID,
|
||||
// LoginIP: ip,
|
||||
// DeviceInfo: deviceID,
|
||||
// LoginResult: success,
|
||||
// FailReason: failReason,
|
||||
// }
|
||||
//
|
||||
// if err := s.logDb.Create(&logEntry).Error; err != nil {
|
||||
// log.ErrorF("记录登录日志失败: %v", err)
|
||||
// }
|
||||
//}
|
||||
// 记录登录日志
|
||||
func (s *UserAccountOp) RecordLoginLog(logEntry *user.UserLoginLog) {
|
||||
if err := s.logDb.Create(&logEntry).Error; err != nil {
|
||||
log.ErrorF("记录登录日志失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//// 生成JWT令牌(简化版)
|
||||
//func generateToken(userID uint, username string) (string, error) {
|
||||
|
83
server/db/server/handlerUser.go
Normal file
83
server/db/server/handlerUser.go
Normal file
@ -0,0 +1,83 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"game/common/model/user"
|
||||
"game/common/proto/pb"
|
||||
"game/server/db/operation"
|
||||
"github.com/fox/fox/ipb"
|
||||
"github.com/fox/fox/log"
|
||||
)
|
||||
|
||||
// 获取帐号
|
||||
func (s *DbService) onGetUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
operationDb[user.UserAccount](iMsg, func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
|
||||
return operation.NewUserAccountOp().GetUserAccount(us.Username)
|
||||
})
|
||||
return iMsg
|
||||
}
|
||||
|
||||
// 创建帐号
|
||||
func (s *DbService) onCreateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
operationDb[user.UserAccount](iMsg, operation.NewUserAccountOp().CreateUserAccount)
|
||||
return iMsg
|
||||
}
|
||||
|
||||
type result[T any] struct {
|
||||
ret T
|
||||
}
|
||||
|
||||
// 装饰器
|
||||
func operationDb[T any](iMsg *ipb.InternalMsg, operation func(table *T) (*T, pb.ErrCode)) {
|
||||
t := result[T]{}
|
||||
err := json.Unmarshal(iMsg.Msg, &t.ret)
|
||||
if err != nil {
|
||||
log.ErrorF("error unmarshalling user account %v", err)
|
||||
return
|
||||
}
|
||||
table, code := operation(&t.ret)
|
||||
if code != pb.ErrCode_OK {
|
||||
return
|
||||
}
|
||||
iMsg.Msg, err = json.Marshal(table)
|
||||
if err != nil {
|
||||
log.ErrorF("error marshalling user account %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
func (s *DbService) onUpdateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
operationDb[user.UserAccount](iMsg, operation.NewUserAccountOp().UpdateUserPassword)
|
||||
return iMsg
|
||||
}
|
||||
|
||||
// 日志操作无需返回值
|
||||
func (s *DbService) onLogUserAccountLogin(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
operationDb[user.UserLoginLog](iMsg, func(us *user.UserLoginLog) (*user.UserLoginLog, pb.ErrCode) {
|
||||
operation.NewUserAccountOp().RecordLoginLog(us)
|
||||
return nil, pb.ErrCode_OK
|
||||
})
|
||||
return iMsg
|
||||
}
|
||||
|
||||
//func (s *DbService) operation(iMsg *ipb.InternalMsg, operation func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode)) {
|
||||
// us := &user.UserAccount{}
|
||||
// err := json.Unmarshal(iMsg.Msg, us)
|
||||
// if err != nil {
|
||||
// log.ErrorF("error unmarshalling user account %v", err)
|
||||
// return
|
||||
// }
|
||||
// var code pb.ErrCode
|
||||
// us, code = operation(us)
|
||||
// if code != pb.ErrCode_OK {
|
||||
// return
|
||||
// }
|
||||
// iMsg.Msg, err = json.Marshal(us)
|
||||
// if err != nil {
|
||||
// log.ErrorF("error marshalling user account %v", err)
|
||||
// return
|
||||
// }
|
||||
// return
|
||||
//}
|
@ -7,8 +7,9 @@ import (
|
||||
|
||||
func (s *DbService) initRpcProcessor() {
|
||||
s.RpcProcessor.RegisterMessages(map[string]processor.RpcHandler{
|
||||
rpcName.CreateUserAccount: s.onCreateUserAccount,
|
||||
rpcName.GetUserAccount: s.onGetUserAccount,
|
||||
rpcName.UpdateUserPassword: s.onUpdateUserAccount,
|
||||
rpcName.CreateUserAccount: s.onCreateUserAccount,
|
||||
rpcName.GetUserAccount: s.onGetUserAccount,
|
||||
rpcName.UpdateUserPassword: s.onUpdateUserAccount,
|
||||
rpcName.LogUserAccountLogin: s.onLogUserAccountLogin,
|
||||
})
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ func Init() {
|
||||
log.DebugF("init service begin id:%v, num:%v", config.Command.ServiceId, config.Command.ServiceNum)
|
||||
for i := 0; i < config.Command.ServiceNum; i++ {
|
||||
sid := config.Command.ServiceId + i
|
||||
if srv := newLoginService(sid); srv != nil {
|
||||
if srv := newDbService(sid); srv != nil {
|
||||
DbSrv = append(DbSrv, srv)
|
||||
}
|
||||
}
|
||||
@ -35,20 +35,20 @@ func Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
func newLoginService(serviceId int) *DbService {
|
||||
func newDbService(serviceId int) *DbService {
|
||||
var err error
|
||||
s := new(DbService)
|
||||
|
||||
sName := fmt.Sprintf("%v-%d", serviceName.Login, serviceId)
|
||||
sName := fmt.Sprintf("%v-%d", serviceName.Db, serviceId)
|
||||
if s.NatsService, err = service.NewNatsService(&service.InitNatsServiceParams{
|
||||
EtcdAddress: config.Cfg.Etcd.Address,
|
||||
EtcdUsername: "",
|
||||
EtcdPassword: "",
|
||||
NatsAddress: config.Cfg.Nats.Address,
|
||||
ServiceType: serviceName.Login,
|
||||
ServiceType: serviceName.Db,
|
||||
ServiceName: sName,
|
||||
OnFunc: s,
|
||||
TypeId: int(pb.ServiceTypeId_STI_Login),
|
||||
TypeId: int(pb.ServiceTypeId_STI_DB),
|
||||
Version: config.Cfg.BuildDate,
|
||||
}); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
@ -80,18 +80,5 @@ func (s *DbService) OnStop() {
|
||||
// 处理其它服发送过来的消息
|
||||
func (s *DbService) OnMessage(data []byte) error {
|
||||
_ = data
|
||||
//log.Debug(s.Log("received message:%v", iMsg.MsgId))
|
||||
return nil
|
||||
}
|
||||
|
||||
//// 向内部服务发送消息
|
||||
//func (s *DbService) SendServiceData(topic string, connId uint32, userId int64, msgId int32, data []byte) {
|
||||
// iMsg := ipb.MakeMsg(s.Name(), connId, userId, msgId, data)
|
||||
// _ = s.Send(topic, iMsg)
|
||||
//}
|
||||
//
|
||||
//// 向内部服务发送消息
|
||||
//func (s *DbService) SendServiceMsg(topic string, connId uint32, userId int64, msgId int32, msg proto.Message) {
|
||||
// data, _ := proto.Marshal(msg)
|
||||
// s.SendServiceData(topic, connId, userId, msgId, data)
|
||||
//}
|
||||
|
@ -1,51 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"game/common/model/user"
|
||||
"game/common/proto/pb"
|
||||
"game/server/db/operation"
|
||||
"github.com/fox/fox/ipb"
|
||||
"github.com/fox/fox/log"
|
||||
)
|
||||
|
||||
// 获取帐号
|
||||
func (s *DbService) onGetUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
s.operation(iMsg, func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
|
||||
return operation.NewUserAccountOp().GetUserAccount(us.Username)
|
||||
})
|
||||
return iMsg
|
||||
}
|
||||
|
||||
// 创建帐号
|
||||
func (s *DbService) onCreateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
s.operation(iMsg, operation.NewUserAccountOp().CreateUserAccount)
|
||||
return iMsg
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
func (s *DbService) operation(iMsg *ipb.InternalMsg, operation func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode)) {
|
||||
us := &user.UserAccount{}
|
||||
err := json.Unmarshal(iMsg.Msg, us)
|
||||
if err != nil {
|
||||
log.ErrorF("error unmarshalling user account %v", err)
|
||||
return
|
||||
}
|
||||
var code pb.ErrCode
|
||||
us, code = operation(us)
|
||||
if code != pb.ErrCode_OK {
|
||||
return
|
||||
}
|
||||
iMsg.Msg, err = json.Marshal(us)
|
||||
if err != nil {
|
||||
log.ErrorF("error marshalling user account %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
func (s *DbService) onUpdateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||
s.operation(iMsg, operation.NewUserAccountOp().UpdateUserPassword)
|
||||
return iMsg
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"game/common/utils"
|
||||
"game/server/gate/config"
|
||||
"github.com/fox/fox/db"
|
||||
"github.com/fox/fox/log"
|
||||
@ -16,4 +17,5 @@ func InitRedis() {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
utils.AutoSetRedisPool(UserRedis)
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ func (s *GateService) WsOnMessage(conn ws.IConn, data []byte) {
|
||||
} else {
|
||||
log.Error(s.Log("topic:%v not exist.user:%v", topic, conn.UserId()))
|
||||
}
|
||||
log.Debug(s.Log("received client:%d user:%v message:%v", conn.Id(), conn.UserId(), msg.MsgId))
|
||||
log.Debug(s.Log("received conn:%d user:%v message:%v", conn.Id(), conn.UserId(), msg.MsgId))
|
||||
}
|
||||
|
||||
// 向内部服务发送消息
|
||||
|
@ -3,7 +3,6 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"game/server/login/config"
|
||||
"game/server/login/model"
|
||||
"game/server/login/server"
|
||||
"github.com/fox/fox/log"
|
||||
"os"
|
||||
@ -12,8 +11,8 @@ import (
|
||||
)
|
||||
|
||||
func initRepo() {
|
||||
model.InitRedis()
|
||||
model.InitDb()
|
||||
//model.InitRedis()
|
||||
//model.InitDb()
|
||||
}
|
||||
|
||||
func Run(GitCommit, GitBranch, BuildDate string) {
|
||||
|
@ -1,59 +1,59 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"game/server/login/config"
|
||||
"github.com/fox/fox/db"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
UserRedis *redis.Client
|
||||
UserDB *gorm.DB
|
||||
LogDB *gorm.DB
|
||||
)
|
||||
|
||||
func InitRedis() {
|
||||
log.Debug("init redis")
|
||||
var err error
|
||||
cfg := &config.Cfg.Redis
|
||||
UserRedis, err = db.InitRedis(cfg.Password, cfg.Host, cfg.Port, 0)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func InitDb() {
|
||||
log.Debug("init db")
|
||||
var err error
|
||||
cfg := &config.Cfg.Mysql
|
||||
UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
cfg = &config.Cfg.MysqlLog
|
||||
LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
// 自动迁移game库表结构
|
||||
err = UserDB.AutoMigrate(
|
||||
&UserAccount{},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
// 自动迁移game_log库表结构
|
||||
err = LogDB.AutoMigrate(
|
||||
&UserLoginLog{},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
//import (
|
||||
// "game/server/login/config"
|
||||
// "github.com/fox/fox/db"
|
||||
// "github.com/fox/fox/log"
|
||||
// "github.com/go-redis/redis/v8"
|
||||
// "gorm.io/gorm"
|
||||
//)
|
||||
//
|
||||
//var (
|
||||
// UserRedis *redis.Client
|
||||
// UserDB *gorm.DB
|
||||
// LogDB *gorm.DB
|
||||
//)
|
||||
//
|
||||
//func InitRedis() {
|
||||
// log.Debug("init redis")
|
||||
// var err error
|
||||
// cfg := &config.Cfg.Redis
|
||||
// UserRedis, err = db.InitRedis(cfg.Password, cfg.Host, cfg.Port, 0)
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func InitDb() {
|
||||
// log.Debug("init db")
|
||||
// var err error
|
||||
// cfg := &config.Cfg.Mysql
|
||||
// UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// return
|
||||
// }
|
||||
// cfg = &config.Cfg.MysqlLog
|
||||
// LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// return
|
||||
// }
|
||||
// // 自动迁移game库表结构
|
||||
// err = UserDB.AutoMigrate(
|
||||
// &UserAccount{},
|
||||
// )
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// return
|
||||
// }
|
||||
// // 自动迁移game_log库表结构
|
||||
// err = LogDB.AutoMigrate(
|
||||
// &UserLoginLog{},
|
||||
// )
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
|
@ -1,152 +1,152 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/fox/fox/log"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
AccountNormal = 1 // 正常
|
||||
AccountFrozen = 2 // 冻结
|
||||
AccountBanned = 3 // 封禁
|
||||
)
|
||||
|
||||
// 玩家账户表
|
||||
type UserAccount struct {
|
||||
gorm.Model
|
||||
Username string `gorm:"type:varchar(32);uniqueIndex;not null"` // 用户名
|
||||
Password string `gorm:"type:varchar(255);not null"` // 密码哈希
|
||||
Email string `gorm:"type:varchar(100)"` // 邮箱(可选)
|
||||
Phone string `gorm:"type:varchar(20)"` // 手机号(可选)
|
||||
DeviceID string `gorm:"type:varchar(64);index"` // 设备ID
|
||||
LastLoginIP string `gorm:"type:varchar(45)"` // 最后登录IP(支持IPv6)
|
||||
LastLoginTime time.Time // 最后登录时间
|
||||
Status int `gorm:"type:tinyint;default:1"` // 账号状态 1-正常 2-冻结 3-封禁
|
||||
RegisterIP string `gorm:"type:varchar(45)"` // 注册IP
|
||||
RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 注册时间
|
||||
}
|
||||
|
||||
// 玩家登录记录表
|
||||
type UserLoginLog struct {
|
||||
gorm.Model
|
||||
PlayerID uint `gorm:"index"` // 关联玩家ID
|
||||
LoginIP string `gorm:"type:varchar(45);not null"` // 登录IP
|
||||
LoginTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 登录时间
|
||||
DeviceInfo string `gorm:"type:varchar(255)"` // 设备信息(JSON格式)
|
||||
LoginResult bool // 登录结果 true-成功 false-失败
|
||||
FailReason string `gorm:"type:varchar(100)"` // 失败原因
|
||||
}
|
||||
|
||||
type UserLoginOp struct {
|
||||
db *gorm.DB
|
||||
logDb *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserLoginOp() *UserLoginOp {
|
||||
return &UserLoginOp{db: UserDB, logDb: LogDB}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrUserOrPassword = errors.New("user or password was error")
|
||||
ErrAccountFrozen = errors.New("account frozen")
|
||||
ErrAccountBanned = errors.New("account banned")
|
||||
)
|
||||
|
||||
func (s *UserLoginOp) Login(username, password, ip, deviceID string) (*UserAccount, error) {
|
||||
var user UserAccount
|
||||
err := s.db.Where("username = ?", username).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 验证密码
|
||||
if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
s.recordLoginLog(user.ID, ip, deviceID, false, ErrUserOrPassword.Error())
|
||||
return nil, ErrUserOrPassword
|
||||
}
|
||||
// 检查账号状态
|
||||
switch user.Status {
|
||||
case AccountNormal:
|
||||
|
||||
case AccountFrozen:
|
||||
s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountFrozen.Error())
|
||||
return nil, ErrAccountFrozen
|
||||
case AccountBanned:
|
||||
s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountBanned.Error())
|
||||
return nil, ErrAccountBanned
|
||||
}
|
||||
// 更新最后登录信息
|
||||
user.LastLoginIP = ip
|
||||
user.LastLoginTime = time.Now()
|
||||
_ = s.db.Save(&user).Error
|
||||
|
||||
// 记录成功登录日志
|
||||
s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
||||
|
||||
// 6. 生成访问令牌
|
||||
token, err := generateToken(user.ID, user.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Password = token
|
||||
return &user, err
|
||||
}
|
||||
|
||||
// 注册新用户
|
||||
func (s *UserLoginOp) RegisterNewUser(username, password, ip, deviceID string) (*UserAccount, error) {
|
||||
// 密码加密
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user := UserAccount{
|
||||
Username: username,
|
||||
Password: string(hashedPassword),
|
||||
DeviceID: deviceID,
|
||||
RegisterIP: ip,
|
||||
Status: 1,
|
||||
LastLoginIP: ip,
|
||||
LastLoginTime: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.db.Create(&user).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
||||
|
||||
// 生成访问令牌
|
||||
token, err := generateToken(user.ID, user.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Password = token
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// 记录登录日志
|
||||
func (s *UserLoginOp) recordLoginLog(userID uint, ip, deviceID string, success bool, failReason string) {
|
||||
logEntry := UserLoginLog{
|
||||
PlayerID: userID,
|
||||
LoginIP: ip,
|
||||
DeviceInfo: deviceID,
|
||||
LoginResult: success,
|
||||
FailReason: failReason,
|
||||
}
|
||||
|
||||
if err := s.logDb.Create(&logEntry).Error; err != nil {
|
||||
log.ErrorF("记录登录日志失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成JWT令牌(简化版)
|
||||
func generateToken(userID uint, username string) (string, error) {
|
||||
_ = userID
|
||||
_ = username
|
||||
// 这里应该使用JWT库生成实际令牌
|
||||
// 简化实现,实际项目中请使用安全的JWT实现
|
||||
return "generated-token-placeholder", nil
|
||||
}
|
||||
//import (
|
||||
// "errors"
|
||||
// "github.com/fox/fox/log"
|
||||
// "golang.org/x/crypto/bcrypt"
|
||||
// "gorm.io/gorm"
|
||||
// "time"
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// AccountNormal = 1 // 正常
|
||||
// AccountFrozen = 2 // 冻结
|
||||
// AccountBanned = 3 // 封禁
|
||||
//)
|
||||
//
|
||||
//// 玩家账户表
|
||||
//type UserAccount struct {
|
||||
// gorm.Model
|
||||
// Username string `gorm:"type:varchar(32);uniqueIndex;not null"` // 用户名
|
||||
// Password string `gorm:"type:varchar(255);not null"` // 密码哈希
|
||||
// Email string `gorm:"type:varchar(100)"` // 邮箱(可选)
|
||||
// Phone string `gorm:"type:varchar(20)"` // 手机号(可选)
|
||||
// DeviceID string `gorm:"type:varchar(64);index"` // 设备ID
|
||||
// LastLoginIP string `gorm:"type:varchar(45)"` // 最后登录IP(支持IPv6)
|
||||
// LastLoginTime time.Time // 最后登录时间
|
||||
// Status int `gorm:"type:tinyint;default:1"` // 账号状态 1-正常 2-冻结 3-封禁
|
||||
// RegisterIP string `gorm:"type:varchar(45)"` // 注册IP
|
||||
// RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 注册时间
|
||||
//}
|
||||
//
|
||||
//// 玩家登录记录表
|
||||
//type UserLoginLog struct {
|
||||
// gorm.Model
|
||||
// PlayerID uint `gorm:"index"` // 关联玩家ID
|
||||
// LoginIP string `gorm:"type:varchar(45);not null"` // 登录IP
|
||||
// LoginTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 登录时间
|
||||
// DeviceInfo string `gorm:"type:varchar(255)"` // 设备信息(JSON格式)
|
||||
// LoginResult bool // 登录结果 true-成功 false-失败
|
||||
// FailReason string `gorm:"type:varchar(100)"` // 失败原因
|
||||
//}
|
||||
//
|
||||
//type UserLoginOp struct {
|
||||
// db *gorm.DB
|
||||
// logDb *gorm.DB
|
||||
//}
|
||||
//
|
||||
//func NewUserLoginOp() *UserLoginOp {
|
||||
// return &UserLoginOp{db: UserDB, logDb: LogDB}
|
||||
//}
|
||||
//
|
||||
//var (
|
||||
// ErrUserOrPassword = errors.New("user or password was error")
|
||||
// ErrAccountFrozen = errors.New("account frozen")
|
||||
// ErrAccountBanned = errors.New("account banned")
|
||||
//)
|
||||
//
|
||||
//func (s *UserLoginOp) Login(username, password, ip, deviceID string) (*UserAccount, error) {
|
||||
// var user UserAccount
|
||||
// err := s.db.Where("username = ?", username).First(&user).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// // 验证密码
|
||||
// if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrUserOrPassword.Error())
|
||||
// return nil, ErrUserOrPassword
|
||||
// }
|
||||
// // 检查账号状态
|
||||
// switch user.Status {
|
||||
// case AccountNormal:
|
||||
//
|
||||
// case AccountFrozen:
|
||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountFrozen.Error())
|
||||
// return nil, ErrAccountFrozen
|
||||
// case AccountBanned:
|
||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountBanned.Error())
|
||||
// return nil, ErrAccountBanned
|
||||
// }
|
||||
// // 更新最后登录信息
|
||||
// user.LastLoginIP = ip
|
||||
// user.LastLoginTime = time.Now()
|
||||
// _ = s.db.Save(&user).Error
|
||||
//
|
||||
// // 记录成功登录日志
|
||||
// s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
||||
//
|
||||
// // 6. 生成访问令牌
|
||||
// token, err := generateToken(user.ID, user.Username)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// user.Password = token
|
||||
// return &user, err
|
||||
//}
|
||||
//
|
||||
//// 注册新用户
|
||||
//func (s *UserLoginOp) RegisterNewUser(username, password, ip, deviceID string) (*UserAccount, error) {
|
||||
// // 密码加密
|
||||
// hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// user := UserAccount{
|
||||
// Username: username,
|
||||
// Password: string(hashedPassword),
|
||||
// DeviceID: deviceID,
|
||||
// RegisterIP: ip,
|
||||
// Status: 1,
|
||||
// LastLoginIP: ip,
|
||||
// LastLoginTime: time.Now(),
|
||||
// }
|
||||
//
|
||||
// if err := s.db.Create(&user).Error; err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
||||
//
|
||||
// // 生成访问令牌
|
||||
// token, err := generateToken(user.ID, user.Username)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// user.Password = token
|
||||
//
|
||||
// return &user, nil
|
||||
//}
|
||||
//
|
||||
//// 记录登录日志
|
||||
//func (s *UserLoginOp) recordLoginLog(userID uint, ip, deviceID string, success bool, failReason string) {
|
||||
// logEntry := UserLoginLog{
|
||||
// PlayerID: userID,
|
||||
// LoginIP: ip,
|
||||
// DeviceInfo: deviceID,
|
||||
// LoginResult: success,
|
||||
// FailReason: failReason,
|
||||
// }
|
||||
//
|
||||
// if err := s.logDb.Create(&logEntry).Error; err != nil {
|
||||
// log.ErrorF("记录登录日志失败: %v", err)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// 生成JWT令牌(简化版)
|
||||
//func generateToken(userID uint, username string) (string, error) {
|
||||
// _ = userID
|
||||
// _ = username
|
||||
// // 这里应该使用JWT库生成实际令牌
|
||||
// // 简化实现,实际项目中请使用安全的JWT实现
|
||||
// return "generated-token-placeholder", nil
|
||||
//}
|
||||
|
@ -1,13 +1,22 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"encoding/json"
|
||||
"game/common/model/user"
|
||||
"game/common/proto/pb"
|
||||
"game/server/login/model"
|
||||
"game/common/rpcName"
|
||||
"game/common/utils"
|
||||
"github.com/fox/fox/etcd"
|
||||
"github.com/fox/fox/ipb"
|
||||
"github.com/fox/fox/ksync"
|
||||
"github.com/fox/fox/log"
|
||||
"github.com/fox/fox/processor"
|
||||
"github.com/fox/fox/service"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
timeout = time.Second * 30
|
||||
)
|
||||
|
||||
func (s *LoginService) initProcessor() {
|
||||
@ -16,42 +25,92 @@ func (s *LoginService) initProcessor() {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *LoginService) checkLoginOrRegister(req *pb.C2SUserLogin) (user *model.UserAccount, code pb.ErrCode) {
|
||||
op := model.NewUserLoginOp()
|
||||
func (s *LoginService) checkLoginOrRegister(req *pb.C2SUserLogin) (us *user.UserAccount, code pb.ErrCode, node *etcd.ServiceNode) {
|
||||
var err error
|
||||
user, err = op.Login(req.Username, req.Password, req.Ip, req.DeviceId)
|
||||
node, err = s.bindService.RandServiceNode(pb.ServiceTypeId_STI_DB)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
user, err = op.RegisterNewUser(req.Username, req.Password, req.Ip, req.DeviceId)
|
||||
if err != nil {
|
||||
code = pb.ErrCode_RegisterUserExist
|
||||
return
|
||||
}
|
||||
} else if errors.Is(err, model.ErrUserOrPassword) {
|
||||
code = pb.ErrCode_LoginUserOrPwdErr
|
||||
return
|
||||
} else if errors.Is(err, model.ErrAccountFrozen) {
|
||||
code = pb.ErrCode_AccountFrozen
|
||||
return
|
||||
} else if errors.Is(err, model.ErrAccountBanned) {
|
||||
code = pb.ErrCode_AccountBanned
|
||||
return
|
||||
} else {
|
||||
code = pb.ErrCode_SystemErr
|
||||
log.ErrorF(s.Log("not find db service.err:%s ", err.Error()))
|
||||
return nil, pb.ErrCode_SystemErr, node
|
||||
}
|
||||
if req.Version < "20250601123030" {
|
||||
return nil, pb.ErrCode_VersionTooLow, node
|
||||
}
|
||||
us = &user.UserAccount{
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
DeviceID: req.DeviceId,
|
||||
LastLoginIP: req.Ip,
|
||||
}
|
||||
rpcMsg := ipb.MakeRpcMsg[user.UserAccount](rpcName.GetUserAccount, 0, us)
|
||||
rspMsg, err := s.Call(service.RpcTopicEx(node.Name), timeout, rpcMsg)
|
||||
if err != nil {
|
||||
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error()))
|
||||
return nil, pb.ErrCode_SystemErr, node
|
||||
}
|
||||
_ = json.Unmarshal(rspMsg.Msg, us)
|
||||
if us.ID == 0 {
|
||||
// 没有帐号,创建帐号
|
||||
rpcMsg.RpcMsgId = rpcName.CreateUserAccount
|
||||
rspMsg, err = s.Call(service.RpcTopicEx(node.Name), timeout, rpcMsg)
|
||||
if err != nil {
|
||||
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error()))
|
||||
return nil, pb.ErrCode_SystemErr, node
|
||||
}
|
||||
_ = json.Unmarshal(rspMsg.Msg, us)
|
||||
if us.ID == 0 {
|
||||
log.ErrorF(s.Log("call rpc:%v err", rpcMsg.RpcMsgId))
|
||||
return nil, pb.ErrCode_SystemErr, node
|
||||
}
|
||||
}
|
||||
return user, code
|
||||
if pwd, _ := utils.Password(req.Password); pwd != us.Password {
|
||||
return nil, pb.ErrCode_LoginUserOrPwdErr, node
|
||||
}
|
||||
switch us.Status {
|
||||
case user.AccountFrozen:
|
||||
return nil, pb.ErrCode_AccountFrozen, node
|
||||
case user.AccountBanned:
|
||||
return nil, pb.ErrCode_AccountBanned, node
|
||||
default:
|
||||
return us, pb.ErrCode_OK, node
|
||||
}
|
||||
}
|
||||
|
||||
// 生成JWT令牌(简化版)
|
||||
func generateToken(userID uint, username string) (string, error) {
|
||||
_ = userID
|
||||
_ = username
|
||||
// 这里应该使用JWT库生成实际令牌
|
||||
// 简化实现,实际项目中请使用安全的JWT实现
|
||||
return "generated-token-placeholder", nil
|
||||
}
|
||||
|
||||
// 登录或注册
|
||||
func (s *LoginService) onLoginOrRegister(iMsg *ipb.InternalMsg, req *pb.C2SUserLogin) {
|
||||
user, code := s.checkLoginOrRegister(req)
|
||||
userId := int64(0)
|
||||
rsp := &pb.S2CUserLogin{Code: code}
|
||||
if user != nil && code == pb.ErrCode_OK {
|
||||
rsp.UserId = int64(user.ID)
|
||||
rsp.Token = user.Password
|
||||
userId = rsp.UserId
|
||||
}
|
||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, userId, int32(pb.MsgId_S2CUserLoginId), rsp)
|
||||
ksync.GoSafe(func() {
|
||||
us, code, node := s.checkLoginOrRegister(req)
|
||||
userId := int64(0)
|
||||
rsp := &pb.S2CUserLogin{Code: code}
|
||||
if us != nil && code == pb.ErrCode_OK {
|
||||
rsp.UserId = int64(us.ID)
|
||||
rsp.Token, _ = generateToken(us.ID, us.Username)
|
||||
userId = rsp.UserId
|
||||
}
|
||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, userId, int32(pb.MsgId_S2CUserLoginId), rsp)
|
||||
|
||||
if us != nil && us.ID > 0 {
|
||||
switch code {
|
||||
case pb.ErrCode_LoginUserOrPwdErr:
|
||||
rpcMsg := ipb.MakeRpcMsg[user.UserLoginLog](rpcName.GetUserAccount, 0, &user.UserLoginLog{
|
||||
UID: us.ID,
|
||||
LoginIP: us.LastLoginIP,
|
||||
LoginTime: time.Now(),
|
||||
DeviceInfo: us.DeviceID,
|
||||
LoginResult: code == pb.ErrCode_OK,
|
||||
FailReason: code.String(),
|
||||
})
|
||||
_, _ = s.Call(service.RpcTopicEx(node.Name), timeout, rpcMsg)
|
||||
}
|
||||
}
|
||||
|
||||
}, nil)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user