game/server/login/server/processor.go

157 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package server
import (
"encoding/json"
"game/common/model/user"
"game/common/proto/pb"
"game/common/rpc"
"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"
"time"
)
const (
timeout = time.Second * 30
)
func (s *LoginService) initProcessor() {
s.processor.RegisterMessages(processor.RegisterMetas{
pb.MsgId_C2SUserLoginId: {pb.C2SUserLogin{}, s.onLoginOrRegister},
})
}
func (s *LoginService) checkLoginOrRegister(req *pb.C2SUserLogin) (us *user.UserAccount, code pb.ErrCode, node *etcd.ServiceNode) {
var err error
node, err = s.bindService.RandServiceNode(pb.ServiceTypeId_STI_DB)
if err != nil {
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](rpc.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)
//log.DebugF("收到rpc:%v返回数据:%v", rpcName.GetUserAccount, string(rspMsg.Msg))
if us.ID == 0 {
// 没有帐号,创建帐号
us = &user.UserAccount{
Username: req.Username,
Password: req.Password,
DeviceID: req.DeviceId,
LastLoginIP: req.Ip,
LastLoginTime: time.Now(),
RegisterIP: req.Ip,
RegisterTime: time.Now(),
}
rpcMsg = ipb.MakeRpcMsg[user.UserAccount](rpc.CreateUserAccount, 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 {
log.ErrorF(s.Log("call rpc:%v err", rpcMsg.RpcMsgId))
return nil, pb.ErrCode_SystemErr, node
}
log.DebugF("收到rcp:%v返回数据:%v", rpc.CreateUserAccount, string(rspMsg.Msg))
}
if !utils.CheckPassword(req.Password, us.Password) {
log.ErrorF(s.Log("用户密码:%v 数据库中密码:%v", req.Password, 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 int64, username string) (string, error) {
_ = userID
_ = username
// 这里应该使用JWT库生成实际令牌
// 简化实现实际项目中请使用安全的JWT实现
return "generated-token-placeholder", nil
}
// 获取用户数据,如果没有则创建
func (s *LoginService) getUser(accountId int64, tName string) (*user.User, pb.ErrCode) {
us := &user.User{
AccountId: accountId,
}
rpcMsg := ipb.MakeRpcMsg[user.User](rpc.GetUserByAccountId, 0, us)
rsp, err := s.Call(service.RpcTopicEx(tName), timeout, rpcMsg)
if err != nil {
log.ErrorF(s.Log("call rpc:%v err:%s", rpcMsg.RpcMsgId, err.Error()))
return nil, pb.ErrCode_SystemErr
}
_ = json.Unmarshal(rsp.Msg, us)
if us.ID == 0 {
log.ErrorF(s.Log("call rpc:%v return:%v", rpcMsg.RpcMsgId, string(rsp.Msg)))
return us, pb.ErrCode_SystemErr
}
return us, pb.ErrCode_OK
}
// 登录或注册
func (s *LoginService) onLoginOrRegister(iMsg *ipb.InternalMsg, req *pb.C2SUserLogin) {
ksync.GoSafe(func() {
account, code, node := s.checkLoginOrRegister(req)
userId := int64(0)
rsp := &pb.S2CUserLogin{Code: code}
if account != nil && code == pb.ErrCode_OK {
// 拉取用户数据
us := &user.User{}
us, code = s.getUser(userId, req.Username)
if code == pb.ErrCode_OK {
rsp.UserId = us.ID
rsp.Token, _ = generateToken(account.ID, account.Username)
userId = rsp.UserId
}
}
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, userId, int32(pb.MsgId_S2CUserLoginId), rsp)
if account != nil && account.ID > 0 {
loginLog := &user.UserLoginLog{
AccountID: account.ID,
LoginIP: req.Ip,
LoginTime: time.Now(),
DeviceInfo: req.DeviceId,
LoginResult: code == pb.ErrCode_OK,
FailReason: code.String(),
}
switch code {
case pb.ErrCode_LoginUserOrPwdErr, pb.ErrCode_OK:
rpcMsg := ipb.MakeRpcMsg[user.UserLoginLog](rpc.LogUserAccountLogin, 0, loginLog)
ksync.GoSafe(func() {
_, _ = s.Call(service.RpcTopicEx(node.Name), timeout, rpcMsg)
}, nil)
}
}
}, nil)
}