系统架构层面流量控制功能完善

This commit is contained in:
flswld
2023-02-05 07:18:43 +08:00
parent cfb001c18a
commit 94c8db402a
51 changed files with 1049 additions and 2408 deletions

View File

@@ -22,24 +22,42 @@ type TokenVerifyRsp struct {
}
func (c *Controller) gateTokenVerify(context *gin.Context) {
tokenVerifyReq := new(TokenVerifyReq)
err := context.ShouldBindJSON(tokenVerifyReq)
if err != nil {
return
}
logger.Debug("gate token verify, req: %v", tokenVerifyReq)
accountId, err := strconv.ParseUint(tokenVerifyReq.AccountId, 10, 64)
if err != nil {
return
}
account, err := c.dao.QueryAccountByField("accountID", accountId)
if err != nil || account == nil {
VerifyFail := func() {
context.JSON(http.StatusOK, &TokenVerifyRsp{
Valid: false,
Forbid: false,
ForbidEndTime: 0,
PlayerID: 0,
})
}
tokenVerifyReq := new(TokenVerifyReq)
err := context.ShouldBindJSON(tokenVerifyReq)
if err != nil {
VerifyFail()
return
}
logger.Info("gate token verify, req: %v", tokenVerifyReq)
accountId, err := strconv.ParseUint(tokenVerifyReq.AccountId, 10, 64)
if err != nil {
VerifyFail()
return
}
account, err := c.dao.QueryAccountByField("accountID", accountId)
if err != nil || account == nil {
VerifyFail()
return
}
if tokenVerifyReq.AccountToken != account.ComboToken {
VerifyFail()
return
}
if account.ComboTokenUsed {
VerifyFail()
return
}
_, err = c.dao.UpdateAccountFieldByFieldName("accountID", account.AccountID, "comboTokenUsed", true)
if err != nil {
VerifyFail()
return
}
context.JSON(http.StatusOK, &TokenVerifyRsp{

View File

@@ -1,6 +1,11 @@
package controller
import "github.com/gin-gonic/gin"
import (
"hk4e/dispatch/model"
"hk4e/pkg/logger"
"github.com/gin-gonic/gin"
)
// POST https://log-upload-os.mihoyo.com/sdk/dataUpload HTTP/1.1
func (c *Controller) sdkDataUpload(context *gin.Context) {
@@ -22,6 +27,17 @@ func (c *Controller) perfDataUpload(context *gin.Context) {
// POST http://overseauspider.yuanshen.com:8888/log HTTP/1.1
func (c *Controller) log8888(context *gin.Context) {
clientLog := new(model.ClientLog)
err := context.ShouldBindJSON(clientLog)
if err != nil {
logger.Error("parse client log error: %v", err)
return
}
_, err = c.dao.InsertClientLog(clientLog)
if err != nil {
logger.Error("insert client log error: %v", err)
return
}
context.Header("Content-type", "application/json")
_, _ = context.Writer.WriteString("{\"code\":0}")
}

View File

@@ -7,6 +7,7 @@ import (
"regexp"
"strconv"
"strings"
"time"
"hk4e/dispatch/api"
"hk4e/dispatch/model"
@@ -98,7 +99,7 @@ func (c *Controller) apiLogin(context *gin.Context) {
return
}
if account == nil {
// 注册一个原神account
// 自动注册
accountId, err := c.dao.GetNextAccountId()
if err != nil {
responseData.Retcode = -201
@@ -138,7 +139,7 @@ func (c *Controller) apiLogin(context *gin.Context) {
context.JSON(http.StatusOK, responseData)
return
}
// 生新的token
// 生新的token
account.Token = base64.StdEncoding.EncodeToString(random.GetRandomByte(24))
_, err = c.dao.UpdateAccountFieldByFieldName("accountID", account.AccountID, "token", account.Token)
if err != nil {
@@ -147,6 +148,13 @@ func (c *Controller) apiLogin(context *gin.Context) {
context.JSON(http.StatusOK, responseData)
return
}
_, err = c.dao.UpdateAccountFieldByFieldName("accountID", account.AccountID, "tokenCreateTime", time.Now().UnixMilli())
if err != nil {
responseData.Retcode = -201
responseData.Message = "服务器内部错误:-5"
context.JSON(http.StatusOK, responseData)
return
}
responseData.Message = "OK"
responseData.Data.Account.Uid = strconv.FormatInt(int64(account.AccountID), 10)
responseData.Data.Account.Token = account.Token
@@ -178,6 +186,12 @@ func (c *Controller) apiVerify(context *gin.Context) {
context.JSON(http.StatusOK, responseData)
return
}
if uint64(time.Now().UnixMilli())-account.TokenCreateTime > uint64(time.Hour.Milliseconds()*24*7) {
responseData.Retcode = -111
responseData.Message = "登录已失效"
context.JSON(http.StatusOK, responseData)
return
}
responseData.Message = "OK"
responseData.Data.Account.Uid = requestData.Uid
responseData.Data.Account.Token = requestData.Token
@@ -225,6 +239,13 @@ func (c *Controller) v2Login(context *gin.Context) {
context.JSON(http.StatusOK, responseData)
return
}
_, err = c.dao.UpdateAccountFieldByFieldName("accountID", account.AccountID, "comboTokenUsed", false)
if err != nil {
responseData.Retcode = -201
responseData.Message = "服务器内部错误:-2"
context.JSON(http.StatusOK, responseData)
return
}
responseData.Message = "OK"
responseData.Data.OpenID = loginData.Uid
responseData.Data.ComboID = "0"

View File

@@ -6,88 +6,10 @@ import (
"hk4e/dispatch/model"
"hk4e/pkg/logger"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
func (d *Dao) _GetNextAccountId() (uint64, error) {
db := d.db.Collection("account_id_counter")
find := db.FindOne(context.TODO(), bson.D{{"_id", "default"}})
item := new(model.AccountIDCounter)
err := find.Decode(item)
if err != nil {
if err == mongo.ErrNoDocuments {
item := &model.AccountIDCounter{
ID: "default",
AccountID: 1,
}
_, err := db.InsertOne(context.TODO(), item)
if err != nil {
return 0, errors.New("insert new AccountID error")
}
return item.AccountID, nil
} else {
return 0, err
}
}
item.AccountID++
_, err = db.UpdateOne(
context.TODO(),
bson.D{
{"_id", "default"},
},
bson.D{
{"$set", bson.D{
{"AccountID", item.AccountID},
}},
},
)
if err != nil {
return 0, err
}
return item.AccountID, nil
}
func (d *Dao) _GetNextYuanShenUid() (uint64, error) {
db := d.db.Collection("player_id_counter")
find := db.FindOne(context.TODO(), bson.D{{"_id", "default"}})
item := new(model.PlayerIDCounter)
err := find.Decode(item)
if err != nil {
if err == mongo.ErrNoDocuments {
item := &model.PlayerIDCounter{
ID: "default",
PlayerID: 100000001,
}
_, err := db.InsertOne(context.TODO(), item)
if err != nil {
return 0, errors.New("insert new PlayerID error")
}
return item.PlayerID, nil
} else {
return 0, err
}
}
item.PlayerID++
_, err = db.UpdateOne(
context.TODO(),
bson.D{
{"_id", "default"},
},
bson.D{
{"$set", bson.D{
{"PlayerID", item.PlayerID},
}},
},
)
if err != nil {
return 0, err
}
return item.PlayerID, nil
}
func (d *Dao) InsertAccount(account *model.Account) (primitive.ObjectID, error) {
db := d.db.Collection("account")
id, err := db.InsertOne(context.TODO(), account)
@@ -103,21 +25,6 @@ func (d *Dao) InsertAccount(account *model.Account) (primitive.ObjectID, error)
}
}
func (d *Dao) DeleteAccountByUsername(username string) (int64, error) {
db := d.db.Collection("account")
deleteCount, err := db.DeleteOne(
context.TODO(),
bson.D{
{"username", username},
},
)
if err != nil {
return 0, err
} else {
return deleteCount.DeletedCount, nil
}
}
func (d *Dao) UpdateAccountFieldByFieldName(fieldName string, fieldValue any, fieldUpdateName string, fieldUpdateValue any) (int64, error) {
db := d.db.Collection("account")
updateCount, err := db.UpdateOne(

View File

@@ -0,0 +1,25 @@
package dao
import (
"context"
"hk4e/dispatch/model"
"hk4e/pkg/logger"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (d *Dao) InsertClientLog(clientLog *model.ClientLog) (primitive.ObjectID, error) {
db := d.db.Collection("client_log")
id, err := db.InsertOne(context.TODO(), clientLog)
if err != nil {
return primitive.ObjectID{}, err
} else {
_id, ok := id.InsertedID.(primitive.ObjectID)
if !ok {
logger.Error("get insert id error")
return primitive.ObjectID{}, nil
}
return _id, nil
}
}

View File

@@ -3,13 +3,15 @@ package model
import "go.mongodb.org/mongo-driver/bson/primitive"
type Account struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
AccountID uint64 `bson:"accountID"`
Username string `bson:"username"`
Password string `bson:"password"`
PlayerID uint64 `bson:"playerID"`
Token string `bson:"token"`
ComboToken string `bson:"comboToken"`
Forbid bool `bson:"forbid"`
ForbidEndTime uint64 `bson:"forbidEndTime"`
ID primitive.ObjectID `bson:"_id,omitempty"`
AccountID uint64 `bson:"accountID"`
Username string `bson:"username"`
Password string `bson:"password"`
PlayerID uint64 `bson:"playerID"`
Token string `bson:"token"`
TokenCreateTime uint64 `bson:"tokenCreateTime"` // 毫秒时间戳
ComboToken string `bson:"comboToken"`
ComboTokenUsed bool `bson:"comboTokenUsed"`
Forbid bool `bson:"forbid"`
ForbidEndTime uint64 `bson:"forbidEndTime"` // 秒时间戳
}

View File

@@ -1,6 +0,0 @@
package model
type AccountIDCounter struct {
ID string `bson:"_id"`
AccountID uint64 `bson:"AccountID"`
}

View File

@@ -0,0 +1,24 @@
package model
import (
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ClientLog struct {
ID primitive.ObjectID `json:"-" bson:"_id,omitempty"`
Auid string `json:"auid" bson:"auid"`
ClientIp string `json:"clientIp" bson:"clientIp"`
CpuInfo string `json:"cpuInfo" bson:"cpuInfo"`
DeviceModel string `json:"deviceModel" bson:"deviceModel"`
DeviceName string `json:"deviceName" bson:"deviceName"`
GpuInfo string `json:"gpuInfo" bson:"gpuInfo"`
Guid string `json:"guid" bson:"guid"`
LogStr string `json:"logStr" bson:"logStr"`
LogType string `json:"logType" bson:"logType"`
OperatingSystem string `json:"operatingSystem" bson:"operatingSystem"`
StackTrace string `json:"stackTrace" bson:"stackTrace"`
Time string `json:"time" bson:"time"`
Uid uint64 `json:"uid" bson:"uid"`
UserName string `json:"userName" bson:"userName"`
Version string `json:"version" bson:"version"`
}

View File

@@ -1,6 +0,0 @@
package model
type PlayerIDCounter struct {
ID string `bson:"_id"`
PlayerID uint64 `bson:"PlayerID"`
}

View File

@@ -1,6 +0,0 @@
package service
type ForbidUserInfo struct {
UserId uint32
ForbidEndTime uint64
}

View File

@@ -8,71 +8,36 @@ type Service struct {
dao *dao.Dao
}
// 用户密码改变
func (f *Service) UserPasswordChange(uid uint32) bool {
// dispatch登录态失效
_, err := f.dao.UpdateAccountFieldByFieldName("accountID", uid, "token", "")
// UserPasswordChange 用户密码改变
func (s *Service) UserPasswordChange(uid uint32) bool {
// http登录态失效
_, err := s.dao.UpdateAccountFieldByFieldName("playerID", uid, "tokenCreateTime", 0)
if err != nil {
return false
}
// 游戏内登录态失效
account, err := f.dao.QueryAccountByField("accountID", uid)
if err != nil {
return false
}
if account == nil {
return false
}
// convId, exist := f.getConvIdByUserId(uint32(account.PlayerID))
// if !exist {
// return true
// }
// f.kcpEventInput <- &net.KcpEvent{
// ConvId: convId,
// EventId: net.KcpConnForceClose,
// EventMessage: uint32(kcp.EnetAccountPasswordChange),
// }
// TODO 游戏内登录态失效
return true
}
// 封号
func (f *Service) ForbidUser(info *ForbidUserInfo) bool {
if info == nil {
return false
}
// ForbidUser 封号
func (s *Service) ForbidUser(uid uint32, forbidEndTime uint64) bool {
// 写入账号封禁信息
_, err := f.dao.UpdateAccountFieldByFieldName("accountID", info.UserId, "forbid", true)
_, err := s.dao.UpdateAccountFieldByFieldName("playerID", uid, "forbid", true)
if err != nil {
return false
}
_, err = f.dao.UpdateAccountFieldByFieldName("accountID", info.UserId, "forbidEndTime", info.ForbidEndTime)
_, err = s.dao.UpdateAccountFieldByFieldName("playerID", uid, "forbidEndTime", forbidEndTime)
if err != nil {
return false
}
// 游戏强制下线
account, err := f.dao.QueryAccountByField("accountID", info.UserId)
if err != nil {
return false
}
if account == nil {
return false
}
// convId, exist := f.getConvIdByUserId(uint32(account.PlayerID))
// if !exist {
// return true
// }
// f.kcpEventInput <- &net.KcpEvent{
// ConvId: convId,
// EventId: net.KcpConnForceClose,
// EventMessage: uint32(kcp.EnetServerKillClient),
// }
// TODO 游戏强制下线
return true
}
// 解封
// UnForbidUser 解封
func (s *Service) UnForbidUser(uid uint32) bool {
// 解除账号封禁
_, err := s.dao.UpdateAccountFieldByFieldName("accountID", uid, "forbid", false)
_, err := s.dao.UpdateAccountFieldByFieldName("playerID", uid, "forbid", false)
if err != nil {
return false
}