mirror of
https://github.com/project-redbud/FunGame-Server.git
synced 2025-04-20 19:19:39 +08:00
服务器结构调整;添加 APIBearer;修复强制下线的目标客户端错误的问题 (#46)
* 服务器结构调整;添加 APIBearer * Server.exe 需要初始化用户密钥列表,UeerKeys 均需要小写用户名保存和读取 * 修复强制下线的目标客户端错误的问题
This commit is contained in:
parent
5f8d8e5214
commit
d35f9aa81a
@ -4,6 +4,7 @@ using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Entity;
|
||||
using Milimoe.FunGame.Core.Interface.Base;
|
||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Common;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
|
||||
@ -27,9 +28,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
|
||||
private DataRequestType _lastRequest = DataRequestType.UnKnown;
|
||||
private readonly bool[] _isReadyCheckCD = [false, false];
|
||||
protected DataSet _dsUser = new();
|
||||
protected string _username = "";
|
||||
protected Guid _checkLoginKey = Guid.Empty;
|
||||
protected bool _isMatching;
|
||||
|
||||
/// <summary>
|
||||
@ -150,12 +149,11 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
{
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest), InvokeMessageType.DataRequest);
|
||||
key = DataRequest.GetDictionaryJsonObject<Guid>(requestData, "key");
|
||||
if (IsLoginKey(key))
|
||||
if (Server.IsLoginKey(key))
|
||||
{
|
||||
// 从玩家列表移除
|
||||
Server.RemoveUser();
|
||||
Server.GetUsersCount();
|
||||
_checkLoginKey = Guid.Empty;
|
||||
msg = "你已成功退出登录! ";
|
||||
}
|
||||
}
|
||||
@ -192,7 +190,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
string gamemap = DataRequest.GetDictionaryJsonObject<string>(requestData, "gamemap") ?? "";
|
||||
bool isrank = DataRequest.GetDictionaryJsonObject<bool>(requestData, "isrank");
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest) + " : " + RoomSet.GetTypeString(type) + " (" + string.Join(", ", [gamemodule, gamemap]) + ")", InvokeMessageType.DataRequest);
|
||||
if (gamemodule == "" || gamemap == "" || Config.GameModuleLoader is null || !Config.GameModuleLoader.ModuleServers.ContainsKey(gamemodule) || !Config.GameModuleLoader.Maps.ContainsKey(gamemap))
|
||||
if (gamemodule == "" || gamemap == "" || FunGameSystem.GameModuleLoader is null || !FunGameSystem.GameModuleLoader.ModuleServers.ContainsKey(gamemodule) || !FunGameSystem.GameModuleLoader.Maps.ContainsKey(gamemap))
|
||||
{
|
||||
ServerHelper.WriteLine("缺少对应的模组或地图,无法创建房间。");
|
||||
resultData.Add("room", room);
|
||||
@ -209,7 +207,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
{
|
||||
// 防止重复
|
||||
roomid = Verification.CreateVerifyCode(VerifyCodeType.MixVerifyCode, 7).ToUpper();
|
||||
if (Config.RoomList.GetRoom(roomid).Roomid == "-1")
|
||||
if (FunGameSystem.RoomList.GetRoom(roomid).Roomid == "-1")
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -224,7 +222,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
if (SQLHelper.Result == SQLResult.Success && SQLHelper.DataSet.Tables[0].Rows.Count > 0)
|
||||
{
|
||||
room = Factory.GetRoom(SQLHelper.DataSet.Tables[0].Rows[0], user);
|
||||
Config.RoomList.AddRoom(room);
|
||||
FunGameSystem.RoomList.AddRoom(room);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,7 +238,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
private void UpdateRoom(Dictionary<string, object> resultData)
|
||||
{
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest), InvokeMessageType.DataRequest);
|
||||
resultData.Add("rooms", Config.RoomList.ListRoom); // 传RoomList
|
||||
resultData.Add("rooms", FunGameSystem.RoomList.ListRoom); // 传RoomList
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -257,7 +255,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
string roomid = DataRequest.GetDictionaryJsonObject<string>(requestData, "roomid") ?? "-1";
|
||||
bool isMaster = DataRequest.GetDictionaryJsonObject<bool>(requestData, "isMaster");
|
||||
|
||||
if (roomid != "-1" && Config.RoomList.IsExist(roomid))
|
||||
if (roomid != "-1" && FunGameSystem.RoomList.IsExist(roomid))
|
||||
{
|
||||
result = await Server.QuitRoom(roomid, isMaster);
|
||||
}
|
||||
@ -285,15 +283,15 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
SQLHelper.ExecuteDataSet(RoomQuery.Select_IsExistRoom(SQLHelper, roomid));
|
||||
if (SQLHelper.Success)
|
||||
{
|
||||
Config.RoomList.IntoRoom(roomid, Server.User);
|
||||
Server.InRoom = Config.RoomList[roomid];
|
||||
FunGameSystem.RoomList.IntoRoom(roomid, Server.User);
|
||||
Server.InRoom = FunGameSystem.RoomList[roomid];
|
||||
await Server.SendClients(Server.Listener.ClientList.Where(c => c != null && roomid == c.InRoom.Roomid && c.User.Id != 0),
|
||||
SocketMessageType.Chat, Server.User.Username, DateTimeUtility.GetNowShortTime() + " [ " + Server.User.Username + " ] 进入了房间。");
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Config.RoomList.RemoveRoom(roomid);
|
||||
FunGameSystem.RoomList.RemoveRoom(roomid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -344,15 +342,15 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
roomid = DataRequest.GetDictionaryJsonObject<string>(requestData, "roomid") ?? "-1";
|
||||
User user = Server.User;
|
||||
|
||||
if (roomid != "-1" && user.Id != 0 && user.Id != Config.RoomList.GetRoomMaster(roomid).Id && !Config.RoomList.GetReadyUserList(roomid).Contains(user))
|
||||
if (roomid != "-1" && user.Id != 0 && user.Id != FunGameSystem.RoomList.GetRoomMaster(roomid).Id && !FunGameSystem.RoomList.GetReadyUserList(roomid).Contains(user))
|
||||
{
|
||||
Config.RoomList.SetReady(roomid, user);
|
||||
FunGameSystem.RoomList.SetReady(roomid, user);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
resultData.Add("result", result);
|
||||
resultData.Add("ready", Config.RoomList.GetReadyUserList(roomid));
|
||||
resultData.Add("notready", Config.RoomList.GetNotReadyUserList(roomid));
|
||||
resultData.Add("ready", FunGameSystem.RoomList.GetReadyUserList(roomid));
|
||||
resultData.Add("notready", FunGameSystem.RoomList.GetNotReadyUserList(roomid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -370,15 +368,15 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
roomid = DataRequest.GetDictionaryJsonObject<string>(requestData, "roomid") ?? "-1";
|
||||
User user = Server.User;
|
||||
|
||||
if (roomid != "-1" && user.Id != 0 && user.Id != Config.RoomList.GetRoomMaster(roomid).Id && Config.RoomList.GetReadyUserList(roomid).Contains(user))
|
||||
if (roomid != "-1" && user.Id != 0 && user.Id != FunGameSystem.RoomList.GetRoomMaster(roomid).Id && FunGameSystem.RoomList.GetReadyUserList(roomid).Contains(user))
|
||||
{
|
||||
Config.RoomList.CancelReady(roomid, user);
|
||||
FunGameSystem.RoomList.CancelReady(roomid, user);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
resultData.Add("result", result);
|
||||
resultData.Add("ready", Config.RoomList.GetReadyUserList(roomid));
|
||||
resultData.Add("notready", Config.RoomList.GetNotReadyUserList(roomid));
|
||||
resultData.Add("ready", FunGameSystem.RoomList.GetReadyUserList(roomid));
|
||||
resultData.Add("notready", FunGameSystem.RoomList.GetNotReadyUserList(roomid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -416,7 +414,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
{
|
||||
if (isMaster)
|
||||
{
|
||||
string[] usernames = [.. Config.RoomList.GetNotReadyUserList(roomid).Select(user => user.Username)];
|
||||
string[] usernames = [.. FunGameSystem.RoomList.GetNotReadyUserList(roomid).Select(user => user.Username)];
|
||||
if (usernames.Length > 0)
|
||||
{
|
||||
if (_isReadyCheckCD[0] == false)
|
||||
@ -437,7 +435,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
List<User> users = Config.RoomList.GetUsers(roomid);
|
||||
List<User> users = FunGameSystem.RoomList.GetUsers(roomid);
|
||||
if (users.Count < 2)
|
||||
{
|
||||
Server.SendSystemMessage(ShowMessageType.None, "玩家数量不足,无法开始游戏。", "", 0, Server.User.Username);
|
||||
@ -455,7 +453,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
{
|
||||
// 提醒房主开始游戏
|
||||
Server.SendSystemMessage(ShowMessageType.None, "已提醒房主立即开始游戏。", "", 0, Server.User.Username);
|
||||
Server.SendSystemMessage(ShowMessageType.Tip, "房间中的玩家已请求你立即开始游戏。", "请求开始", 10, Config.RoomList[roomid].RoomMaster.Username);
|
||||
Server.SendSystemMessage(ShowMessageType.Tip, "房间中的玩家已请求你立即开始游戏。", "请求开始", 10, FunGameSystem.RoomList[roomid].RoomMaster.Username);
|
||||
_isReadyCheckCD[1] = true;
|
||||
TaskUtility.RunTimer(() =>
|
||||
{
|
||||
@ -476,15 +474,15 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
Room room = General.HallInstance;
|
||||
if (roomid != "-1")
|
||||
{
|
||||
room = Config.RoomList[roomid];
|
||||
room = FunGameSystem.RoomList[roomid];
|
||||
}
|
||||
if (room.Roomid == "-1") return;
|
||||
// 启动服务器
|
||||
TaskUtility.NewTask(() =>
|
||||
{
|
||||
if (Config.GameModuleLoader != null && Config.GameModuleLoader.ModuleServers.ContainsKey(room.GameModule))
|
||||
if (FunGameSystem.GameModuleLoader != null && FunGameSystem.GameModuleLoader.ModuleServers.ContainsKey(room.GameModule))
|
||||
{
|
||||
Server.NowGamingServer = Config.GameModuleLoader.GetServerMode(room.GameModule);
|
||||
Server.NowGamingServer = FunGameSystem.GameModuleLoader.GetServerMode(room.GameModule);
|
||||
Dictionary<string, IServerModel> all = Server.Listener.UserList.Cast<IServerModel>().ToDictionary(k => k.User.Username, v => v);
|
||||
// 给其他玩家赋值模组服务器
|
||||
foreach (IServerModel model in all.Values.Where(s => s.User.Username != Server.User.Username))
|
||||
@ -499,7 +497,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
{
|
||||
if (serverTask != null && serverTask.Socket != null)
|
||||
{
|
||||
Config.RoomList.CancelReady(roomid, serverTask.User);
|
||||
FunGameSystem.RoomList.CancelReady(roomid, serverTask.User);
|
||||
serverTask.Send(SocketMessageType.StartGame, room, users);
|
||||
}
|
||||
}
|
||||
@ -529,7 +527,11 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
string password = DataRequest.GetDictionaryJsonObject<string>(requestData, "password") ?? "";
|
||||
string email = DataRequest.GetDictionaryJsonObject<string>(requestData, "email") ?? "";
|
||||
string verifycode = DataRequest.GetDictionaryJsonObject<string>(requestData, "verifycode") ?? "";
|
||||
(msg, returnType, success) = DataRequestService.Reg(username, password, email, verifycode, Server.Socket?.ClientIP ?? "", SQLHelper, MailSender);
|
||||
(msg, returnType, success) = DataRequestService.Reg(Server, username, password, email, verifycode, Server.Socket?.ClientIP ?? "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerHelper.WriteLine("客户端提供的参数不足。", InvokeMessageType.DataRequest, LogLevel.Warning);
|
||||
}
|
||||
resultData.Add("msg", msg);
|
||||
resultData.Add("type", returnType);
|
||||
@ -547,106 +549,69 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
/// <param name="resultData"></param>
|
||||
private async Task Login(Dictionary<string, object> requestData, Dictionary<string, object> resultData)
|
||||
{
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest), InvokeMessageType.DataRequest);
|
||||
string msg = "";
|
||||
User user = Factory.GetUser();
|
||||
|
||||
string username = "";
|
||||
string password = "";
|
||||
string autokey = "";
|
||||
Guid key = Guid.Empty;
|
||||
if (requestData.Count >= 4)
|
||||
{
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest), InvokeMessageType.DataRequest);
|
||||
string username = DataRequest.GetDictionaryJsonObject<string>(requestData, "username") ?? "";
|
||||
string password = DataRequest.GetDictionaryJsonObject<string>(requestData, "password") ?? "";
|
||||
string autokey = DataRequest.GetDictionaryJsonObject<string>(requestData, "autokey") ?? "";
|
||||
Guid key = DataRequest.GetDictionaryJsonObject<Guid>(requestData, "key");
|
||||
username = DataRequest.GetDictionaryJsonObject<string>(requestData, "username") ?? "";
|
||||
password = DataRequest.GetDictionaryJsonObject<string>(requestData, "password") ?? "";
|
||||
autokey = DataRequest.GetDictionaryJsonObject<string>(requestData, "autokey") ?? "";
|
||||
key = DataRequest.GetDictionaryJsonObject<Guid>(requestData, "key");
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerHelper.WriteLine("客户端提供的参数不足。", InvokeMessageType.DataRequest, LogLevel.Warning);
|
||||
}
|
||||
|
||||
// CheckLogin的情况
|
||||
if (key != Guid.Empty)
|
||||
LoginEventArgs eventArgs = new(username, password, autokey);
|
||||
FunGameSystem.ServerPluginLoader?.OnBeforeLoginEvent(this, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnBeforeLoginEvent(this, eventArgs);
|
||||
if (eventArgs.Cancel)
|
||||
{
|
||||
msg = $"{DataRequestSet.GetTypeString(_lastRequest)} 请求已取消。{(eventArgs.EventMsg != "" ? $"原因:{eventArgs.EventMsg}" : "")}";
|
||||
ServerHelper.WriteLine(msg);
|
||||
resultData.Add("msg", msg);
|
||||
resultData.Add("user", user);
|
||||
return;
|
||||
}
|
||||
|
||||
// CheckLogin的情况
|
||||
if (key != Guid.Empty)
|
||||
{
|
||||
if (Server.IsLoginKey(key))
|
||||
{
|
||||
if (IsLoginKey(key))
|
||||
{
|
||||
await CheckLogin();
|
||||
user = Server.User;
|
||||
}
|
||||
else ServerHelper.WriteLine("客户端发送了错误的秘钥,不允许本次登录。");
|
||||
await Server.CheckLogin();
|
||||
user = Server.User;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 验证登录
|
||||
if (username != null && password != null)
|
||||
{
|
||||
password = password.Encrypt(username);
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] Username: " + username);
|
||||
if (SQLHelper != null)
|
||||
{
|
||||
SQLHelper.ExecuteDataSet(UserQuery.Select_Users_LoginQuery(SQLHelper, username, password));
|
||||
if (SQLHelper.Result == SQLResult.Success)
|
||||
{
|
||||
DataSet dsUser = SQLHelper.DataSet;
|
||||
if (autokey.Trim() != "")
|
||||
{
|
||||
SQLHelper.ExecuteDataSet(UserQuery.Select_CheckAutoKey(SQLHelper, username, autokey));
|
||||
if (SQLHelper.Result == SQLResult.Success)
|
||||
{
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] AutoKey: 已确认");
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "AutoKey不正确,拒绝自动登录!";
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] " + msg);
|
||||
}
|
||||
}
|
||||
key = Guid.NewGuid();
|
||||
PreLogin(dsUser, username, key);
|
||||
resultData.Add("key", key);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "用户名或密码不正确。";
|
||||
ServerHelper.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
msg = "客户端发送了错误的秘钥,不允许本次登录。";
|
||||
ServerHelper.WriteLine(msg, InvokeMessageType.DataRequest, LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 进行预登录
|
||||
(bool success, DataSet dsUser, msg, key) = DataRequestService.PreLogin(this, username, password, autokey);
|
||||
if (success)
|
||||
{
|
||||
Server.PreLogin(dsUser, key);
|
||||
resultData.Add("key", key);
|
||||
}
|
||||
}
|
||||
|
||||
FunGameSystem.ServerPluginLoader?.OnAfterLoginEvent(this, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnAfterLoginEvent(this, eventArgs);
|
||||
resultData.Add("msg", msg);
|
||||
resultData.Add("user", user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预登录
|
||||
/// </summary>
|
||||
/// <param name="dsuser"></param>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="checkloginkey"></param>
|
||||
private void PreLogin(DataSet dsuser, string username, Guid checkloginkey)
|
||||
{
|
||||
_dsUser = dsuser;
|
||||
_username = username;
|
||||
_checkLoginKey = checkloginkey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确认登录
|
||||
/// </summary>
|
||||
private async Task CheckLogin()
|
||||
{
|
||||
// 创建User对象
|
||||
Server.User = Factory.GetUser(_dsUser);
|
||||
// 检查有没有重复登录的情况
|
||||
await Server.ForceLogOutDuplicateLogonUser();
|
||||
// 添加至玩家列表
|
||||
Server.AddUser();
|
||||
Server.GetUsersCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查LoginKey
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private bool IsLoginKey(Guid key)
|
||||
{
|
||||
return key == _checkLoginKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收并验证找回密码时的验证码
|
||||
/// </summary>
|
||||
@ -773,7 +738,8 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
string password = DataRequest.GetDictionaryJsonObject<string>(requestData, UserQuery.Column_Password) ?? "";
|
||||
if (username.Trim() != "" && password.Trim() != "")
|
||||
{
|
||||
password = password.Encrypt(username);
|
||||
FunGameSystem.UpdateUserKey(username);
|
||||
password = password.Encrypt(FunGameSystem.GetUserKey(username));
|
||||
SQLHelper?.Execute(UserQuery.Update_Password(SQLHelper, username, password));
|
||||
if (SQLHelper?.Success ?? false)
|
||||
{
|
||||
@ -802,7 +768,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
ServerHelper.WriteLine(Server.GetClientName() + " -> " + DataRequestSet.GetTypeString(_lastRequest), InvokeMessageType.DataRequest);
|
||||
roomid = DataRequest.GetDictionaryJsonObject<string>(requestData, "roomid") ?? "-1";
|
||||
}
|
||||
resultData.Add("count", Config.RoomList.GetUserCount(roomid));
|
||||
resultData.Add("count", FunGameSystem.RoomList.GetUserCount(roomid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -863,11 +829,11 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
List<Room> targets;
|
||||
if (roomtype == RoomType.All)
|
||||
{
|
||||
targets = [.. Config.RoomList.ListRoom.Where(r => r.RoomState == RoomState.Created || r.RoomState == RoomState.Matching)];
|
||||
targets = [.. FunGameSystem.RoomList.ListRoom.Where(r => r.RoomState == RoomState.Created || r.RoomState == RoomState.Matching)];
|
||||
}
|
||||
else
|
||||
{
|
||||
targets = [.. Config.RoomList.ListRoom.Where(r => (r.RoomState == RoomState.Created || r.RoomState == RoomState.Matching) && r.RoomType == roomtype)];
|
||||
targets = [.. FunGameSystem.RoomList.ListRoom.Where(r => (r.RoomState == RoomState.Created || r.RoomState == RoomState.Matching) && r.RoomType == roomtype)];
|
||||
}
|
||||
|
||||
// 如果匹配停止,则退出
|
||||
@ -876,7 +842,7 @@ namespace Milimoe.FunGame.Server.Controller
|
||||
foreach (Room room in targets)
|
||||
{
|
||||
// 获取当前房间的玩家列表
|
||||
List<User> players = Config.RoomList.GetUsers(room.Roomid);
|
||||
List<User> players = FunGameSystem.RoomList.GetUsers(room.Roomid);
|
||||
if (players.Count > 0)
|
||||
{
|
||||
// 计算房间平均Elo
|
||||
|
@ -105,6 +105,9 @@ void StartServer()
|
||||
|
||||
ServerHelper.WriteLine("请输入 help 来获取帮助,按下 Ctrl+C 关闭服务器。");
|
||||
|
||||
// 初始化用户密钥列表
|
||||
FunGameSystem.InitUserKeys();
|
||||
|
||||
ServerHelper.PrintFunGameTitle();
|
||||
|
||||
// 使用Socket还是WebSocket
|
||||
|
@ -52,16 +52,16 @@ namespace Milimoe.FunGame.Server.Model
|
||||
break;
|
||||
}
|
||||
// 广播到插件
|
||||
if (Config.ServerPluginLoader != null)
|
||||
if (FunGameSystem.ServerPluginLoader != null)
|
||||
{
|
||||
foreach (ServerPlugin plugin in Config.ServerPluginLoader.Plugins.Values)
|
||||
foreach (ServerPlugin plugin in FunGameSystem.ServerPluginLoader.Plugins.Values)
|
||||
{
|
||||
plugin.ProcessInput(order);
|
||||
}
|
||||
}
|
||||
if (Config.WebAPIPluginLoader != null)
|
||||
if (FunGameSystem.WebAPIPluginLoader != null)
|
||||
{
|
||||
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
|
||||
foreach (WebAPIPlugin plugin in FunGameSystem.WebAPIPluginLoader.Plugins.Values)
|
||||
{
|
||||
plugin.ProcessInput(order);
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ namespace Milimoe.FunGame.Server.Model
|
||||
protected string _username = "";
|
||||
protected long _loginTime = 0;
|
||||
protected long _logoutTime = 0;
|
||||
protected DataSet _dsUser = new();
|
||||
protected Guid _checkLoginKey = Guid.Empty;
|
||||
|
||||
public ServerModel(ISocketListener<T> server, ISocketMessageProcessor socket, bool isDebugMode)
|
||||
{
|
||||
@ -259,9 +261,9 @@ namespace Milimoe.FunGame.Server.Model
|
||||
else
|
||||
{
|
||||
// 建立连接
|
||||
if (Config.GameModuleLoader != null && Config.GameModuleLoader.ModuleServers.ContainsKey(serverName))
|
||||
if (FunGameSystem.GameModuleLoader != null && FunGameSystem.GameModuleLoader.ModuleServers.ContainsKey(serverName))
|
||||
{
|
||||
GameModuleServer mod = Config.GameModuleLoader.GetServerMode(serverName);
|
||||
GameModuleServer mod = FunGameSystem.GameModuleLoader.GetServerMode(serverName);
|
||||
if (mod.StartAnonymousServer(this, data))
|
||||
{
|
||||
NowGamingServer = mod;
|
||||
@ -381,13 +383,13 @@ namespace Milimoe.FunGame.Server.Model
|
||||
{
|
||||
bool result;
|
||||
|
||||
Config.RoomList.CancelReady(roomid, User);
|
||||
Config.RoomList.QuitRoom(roomid, User);
|
||||
Room Room = Config.RoomList[roomid] ?? General.HallInstance;
|
||||
FunGameSystem.RoomList.CancelReady(roomid, User);
|
||||
FunGameSystem.RoomList.QuitRoom(roomid, User);
|
||||
Room Room = FunGameSystem.RoomList[roomid] ?? General.HallInstance;
|
||||
// 是否是房主
|
||||
if (isMaster)
|
||||
{
|
||||
List<User> users = [.. Config.RoomList[roomid].UserAndIsReady.Keys];
|
||||
List<User> users = [.. FunGameSystem.RoomList[roomid].UserAndIsReady.Keys];
|
||||
if (users.Count > 0) // 如果此时房间还有人,更新房主
|
||||
{
|
||||
User NewMaster = users[0];
|
||||
@ -399,7 +401,7 @@ namespace Milimoe.FunGame.Server.Model
|
||||
}
|
||||
else // 没人了就解散房间
|
||||
{
|
||||
Config.RoomList.RemoveRoom(roomid);
|
||||
FunGameSystem.RoomList.RemoveRoom(roomid);
|
||||
SQLHelper?.Execute(RoomQuery.Delete_QuitRoom(SQLHelper, roomid, User.Id));
|
||||
this.InRoom = General.HallInstance;
|
||||
ServerHelper.WriteLine("[ " + GetClientName() + " ] 解散了房间 " + roomid);
|
||||
@ -421,10 +423,13 @@ namespace Milimoe.FunGame.Server.Model
|
||||
{
|
||||
foreach (IServerModel Client in Listener.ClientList.Where(c => c != null && c.User.Id != 0 && room.Roomid == c.InRoom?.Roomid))
|
||||
{
|
||||
await Client.Send(SocketMessageType.Chat, User.Username, DateTimeUtility.GetNowShortTime() + " [ " + User.Username + " ] 离开了房间。");
|
||||
if (isUpdateRoomMaster && room.RoomMaster?.Id != 0 && room.Roomid != "-1")
|
||||
if (room.Roomid != "-1")
|
||||
{
|
||||
await Client.Send(SocketMessageType.UpdateRoomMaster, room);
|
||||
await Client.Send(SocketMessageType.Chat, User.Username, DateTimeUtility.GetNowShortTime() + " [ " + User.Username + " ] 离开了房间。");
|
||||
if (isUpdateRoomMaster && room.RoomMaster?.Id != 0)
|
||||
{
|
||||
await Client.Send(SocketMessageType.UpdateRoomMaster, room);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -453,11 +458,28 @@ namespace Milimoe.FunGame.Server.Model
|
||||
if (Listener.UserList.ContainsKey(user))
|
||||
{
|
||||
ServerHelper.WriteLine("OnlinePlayers: 玩家 " + user + " 重复登录!");
|
||||
await ForceLogOut("您的账号在别处登录,已强制下线。");
|
||||
await ((ServerModel<T>)Listener.UserList[user]).ForceLogOut("您的账号在别处登录,已强制下线。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PreLogin(DataSet dsuser, Guid checkloginkey)
|
||||
{
|
||||
_dsUser = dsuser;
|
||||
_checkLoginKey = checkloginkey;
|
||||
}
|
||||
|
||||
public async Task CheckLogin()
|
||||
{
|
||||
// 创建User对象
|
||||
User = Factory.GetUser(_dsUser);
|
||||
// 检查有没有重复登录的情况
|
||||
await ForceLogOutDuplicateLogonUser();
|
||||
// 添加至玩家列表
|
||||
AddUser();
|
||||
GetUsersCount();
|
||||
}
|
||||
|
||||
public bool AddUser()
|
||||
{
|
||||
if (User.Id != 0 && this != null)
|
||||
@ -477,6 +499,7 @@ namespace Milimoe.FunGame.Server.Model
|
||||
{
|
||||
if (User.Id != 0 && this != null)
|
||||
{
|
||||
_checkLoginKey = Guid.Empty;
|
||||
_logoutTime = DateTime.Now.Ticks;
|
||||
int TotalMinutes = Convert.ToInt32((new DateTime(_logoutTime) - new DateTime(_loginTime)).TotalMinutes);
|
||||
SQLHelper?.Execute(UserQuery.Update_GameTime(SQLHelper, User.Username, TotalMinutes));
|
||||
@ -501,6 +524,11 @@ namespace Milimoe.FunGame.Server.Model
|
||||
ServerHelper.WriteLine($"{Listener.Name} 的目前在线客户端数量: {Listener.ClientList.Count}(已登录的玩家数量:{Listener.UserList.Count})");
|
||||
}
|
||||
|
||||
public bool IsLoginKey(Guid key)
|
||||
{
|
||||
return key == _checkLoginKey;
|
||||
}
|
||||
|
||||
protected virtual async Task<bool> Read(ISocketMessageProcessor socket)
|
||||
{
|
||||
// 接收客户端消息
|
||||
|
@ -139,35 +139,10 @@ namespace Milimoe.FunGame.Server.Others
|
||||
public static FunGameInfo.FunGame FunGameType => FunGameInfo.FunGame.FunGame_Server;
|
||||
|
||||
/// <summary>
|
||||
/// 服务器指令列表
|
||||
/// </summary>
|
||||
public static Hashtable OrderList { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 在线房间列表
|
||||
/// </summary>
|
||||
public static RoomList RoomList { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否运行数据库模式
|
||||
/// 运行的数据库模式
|
||||
/// </summary>
|
||||
public static SQLMode SQLMode { get; set; } = SQLMode.None;
|
||||
|
||||
/// <summary>
|
||||
/// Server实际安装的模组
|
||||
/// </summary>
|
||||
public static GameModuleLoader? GameModuleLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Server插件
|
||||
/// </summary>
|
||||
public static ServerPluginLoader? ServerPluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Web API插件
|
||||
/// </summary>
|
||||
public static WebAPIPluginLoader? WebAPIPluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 未Loadmodules时,此属性表示至少需要安装的模组
|
||||
/// </summary>
|
||||
|
@ -1,5 +1,7 @@
|
||||
using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using System.Data;
|
||||
using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Common;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
|
||||
@ -9,15 +11,25 @@ namespace Milimoe.FunGame.Server.Services
|
||||
{
|
||||
public class DataRequestService
|
||||
{
|
||||
public static (string Msg, RegInvokeType RegInvokeType, bool Success) Reg(string username, string password, string email, string verifyCode, string clientIP = "", SQLHelper? sqlHelper = null, MailSender? mailSender = null)
|
||||
public static (string Msg, RegInvokeType RegInvokeType, bool Success) Reg(object sender, string username, string password, string email, string verifyCode, string clientIP = "")
|
||||
{
|
||||
string msg = "";
|
||||
RegInvokeType type = RegInvokeType.None;
|
||||
bool success = false;
|
||||
string clientName = ServerHelper.MakeClientName(clientIP);
|
||||
|
||||
sqlHelper ??= Factory.OpenFactory.GetSQLHelper();
|
||||
mailSender ??= Factory.OpenFactory.GetMailSender();
|
||||
RegisterEventArgs eventArgs = new(username, password, email);
|
||||
FunGameSystem.ServerPluginLoader?.OnBeforeRegEvent(sender, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnBeforeRegEvent(sender, eventArgs);
|
||||
if (eventArgs.Cancel)
|
||||
{
|
||||
msg = $"{DataRequestSet.GetTypeString(DataRequestType.Reg_Reg)} 请求已取消。{(eventArgs.EventMsg != "" ? $"原因:{eventArgs.EventMsg}" : "")}";
|
||||
ServerHelper.WriteLine(msg, InvokeMessageType.DataRequest, LogLevel.Warning);
|
||||
return (eventArgs.EventMsg, RegInvokeType.None, false);
|
||||
}
|
||||
|
||||
using SQLHelper? sqlHelper = Factory.OpenFactory.GetSQLHelper();
|
||||
using MailSender? mailSender = Factory.OpenFactory.GetMailSender();
|
||||
if (sqlHelper != null)
|
||||
{
|
||||
// 如果没发验证码,就生成验证码
|
||||
@ -114,6 +126,8 @@ namespace Milimoe.FunGame.Server.Services
|
||||
{
|
||||
sqlHelper.NewTransaction();
|
||||
ServerHelper.WriteLine("[Reg] Username: " + username + " Email: " + email);
|
||||
FunGameSystem.UpdateUserKey(username);
|
||||
password = password.Encrypt(FunGameSystem.GetUserKey(username));
|
||||
sqlHelper.Execute(UserQuery.Insert_Register(sqlHelper, username, password, email, clientIP));
|
||||
if (sqlHelper.Result == SQLResult.Success)
|
||||
{
|
||||
@ -136,7 +150,69 @@ namespace Milimoe.FunGame.Server.Services
|
||||
}
|
||||
}
|
||||
|
||||
eventArgs.Success = success;
|
||||
FunGameSystem.ServerPluginLoader?.OnAfterRegEvent(sender, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnAfterRegEvent(sender, eventArgs);
|
||||
|
||||
return (msg, type, success);
|
||||
}
|
||||
|
||||
public static (bool Success, DataSet DataSet, string Msg, Guid Key) PreLogin(object sender, string username, string password, string autokey = "")
|
||||
{
|
||||
bool success = false;
|
||||
DataSet dsUser = new();
|
||||
string msg = "用户名或密码不正确。";
|
||||
Guid key = Guid.Empty;
|
||||
|
||||
LoginEventArgs eventArgs = new(username, password, autokey);
|
||||
FunGameSystem.ServerPluginLoader?.OnBeforeLoginEvent(sender, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnBeforeLoginEvent(sender, eventArgs);
|
||||
if (eventArgs.Cancel)
|
||||
{
|
||||
msg = $"{DataRequestSet.GetTypeString(DataRequestType.Login_Login)} 请求已取消。{(eventArgs.EventMsg != "" ? $"原因:{eventArgs.EventMsg}" : "")}";
|
||||
ServerHelper.WriteLine(msg, InvokeMessageType.DataRequest, LogLevel.Warning);
|
||||
return (success, dsUser, eventArgs.EventMsg, key);
|
||||
}
|
||||
|
||||
// 验证登录
|
||||
if (username != "" && password != "")
|
||||
{
|
||||
password = password.Encrypt(FunGameSystem.GetUserKey(username));
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] Username: " + username);
|
||||
using SQLHelper? sqlHelper = Factory.OpenFactory.GetSQLHelper();
|
||||
if (sqlHelper != null)
|
||||
{
|
||||
sqlHelper.ExecuteDataSet(UserQuery.Select_Users_LoginQuery(sqlHelper, username, password));
|
||||
if (sqlHelper.Result == SQLResult.Success)
|
||||
{
|
||||
dsUser = sqlHelper.DataSet;
|
||||
key = Guid.NewGuid();
|
||||
success = true;
|
||||
msg = "";
|
||||
if (autokey.Trim() != "")
|
||||
{
|
||||
sqlHelper.ExecuteDataSet(UserQuery.Select_CheckAutoKey(sqlHelper, username, autokey));
|
||||
if (sqlHelper.Result == SQLResult.Success)
|
||||
{
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] AutoKey: 已确认");
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
msg = "AutoKey 不正确,拒绝自动登录!";
|
||||
ServerHelper.WriteLine("[" + DataRequestSet.GetTypeString(DataRequestType.Login_Login) + "] " + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventArgs.Success = success;
|
||||
FunGameSystem.ServerPluginLoader?.OnAfterLoginEvent(sender, eventArgs);
|
||||
FunGameSystem.WebAPIPluginLoader?.OnAfterLoginEvent(sender, eventArgs);
|
||||
|
||||
ServerHelper.WriteLine(msg, InvokeMessageType.Core);
|
||||
return (success, dsUser, msg, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,9 @@ using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Model;
|
||||
using Milimoe.FunGame.Server.Models;
|
||||
using Milimoe.FunGame.Server.Services;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace Milimoe.FunGame.Server.DataUtility
|
||||
namespace Milimoe.FunGame.Server.Services.DataUtility
|
||||
{
|
||||
public class MySQLHelper : SQLHelper
|
||||
{
|
||||
@ -187,6 +186,29 @@ namespace Milimoe.FunGame.Server.DataUtility
|
||||
return _dataSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查数据库是否存在
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool DatabaseExists()
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ServerHelper.Error(e);
|
||||
_result = SQLResult.Fail;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个SQL事务
|
||||
/// </summary>
|
@ -4,9 +4,8 @@ using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Model;
|
||||
using Milimoe.FunGame.Server.Models;
|
||||
using Milimoe.FunGame.Server.Services;
|
||||
|
||||
namespace Milimoe.FunGame.Server.DataUtility
|
||||
namespace Milimoe.FunGame.Server.Services.DataUtility
|
||||
{
|
||||
public class SQLiteHelper : SQLHelper
|
||||
{
|
||||
@ -244,35 +243,11 @@ namespace Milimoe.FunGame.Server.DataUtility
|
||||
/// 检查数据库是否存在
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool DatabaseExists()
|
||||
public override bool DatabaseExists()
|
||||
{
|
||||
return File.Exists(ServerInfo.SQLServerDataBase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行SQL文件中的所有SQL语句来初始化数据库
|
||||
/// </summary>
|
||||
/// <param name="sqlFilePath">SQL文件路径</param>
|
||||
public void ExecuteSqlFile(string sqlFilePath)
|
||||
{
|
||||
if (!File.Exists(sqlFilePath))
|
||||
{
|
||||
throw new FileNotFoundException("SQL文件不存在", sqlFilePath);
|
||||
}
|
||||
|
||||
string sqlContent = File.ReadAllText(sqlFilePath);
|
||||
string[] sqlCommands = sqlContent.Split([";"], StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (string commandText in sqlCommands)
|
||||
{
|
||||
string sql = commandText.Trim();
|
||||
if (!string.IsNullOrEmpty(sql))
|
||||
{
|
||||
Execute(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isDisposed = false;
|
||||
|
||||
/// <summary>
|
@ -1,16 +1,53 @@
|
||||
using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using System.Collections;
|
||||
using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Common;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
|
||||
using Milimoe.FunGame.Server.DataUtility;
|
||||
using Milimoe.FunGame.Core.Model;
|
||||
using Milimoe.FunGame.Server.Others;
|
||||
using Milimoe.FunGame.Server.Services.DataUtility;
|
||||
|
||||
namespace Milimoe.FunGame.Server.Services
|
||||
{
|
||||
public class FunGameSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 服务器指令列表
|
||||
/// </summary>
|
||||
public static Hashtable OrderList { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 在线房间列表
|
||||
/// </summary>
|
||||
public static RoomList RoomList { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Server实际安装的模组
|
||||
/// </summary>
|
||||
public static GameModuleLoader? GameModuleLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Server插件
|
||||
/// </summary>
|
||||
public static ServerPluginLoader? ServerPluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Web API插件
|
||||
/// </summary>
|
||||
public static WebAPIPluginLoader? WebAPIPluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务器配置
|
||||
/// </summary>
|
||||
public static PluginConfig UserKeys { get; set; } = new("system", "user_keys");
|
||||
|
||||
/// <summary>
|
||||
/// FunGame Web API Token ID
|
||||
/// </summary>
|
||||
public const string FunGameWebAPITokenID = "fungame_web_api";
|
||||
|
||||
/// <summary>
|
||||
/// 初始化数据库连接器
|
||||
/// </summary>
|
||||
@ -98,14 +135,14 @@ namespace Milimoe.FunGame.Server.Services
|
||||
// 读取modules目录下的模组
|
||||
try
|
||||
{
|
||||
Config.GameModuleLoader = GameModuleLoader.LoadGameModules(Config.FunGameType, delegates);
|
||||
foreach (GameModuleServer module in Config.GameModuleLoader.ModuleServers.Values)
|
||||
GameModuleLoader = GameModuleLoader.LoadGameModules(Config.FunGameType, delegates);
|
||||
foreach (GameModuleServer module in GameModuleLoader.ModuleServers.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool check = true;
|
||||
// 检查模组是否有相对应的地图
|
||||
if (!Config.GameModuleLoader.Maps.ContainsKey(module.DefaultMap))
|
||||
if (!GameModuleLoader.Maps.ContainsKey(module.DefaultMap))
|
||||
{
|
||||
ServerHelper.WriteLine("GameModule Load Failed: " + module.Name + " 没有找到相对应的地图,加载失败", InvokeMessageType.Error);
|
||||
check = false;
|
||||
@ -127,7 +164,7 @@ namespace Milimoe.FunGame.Server.Services
|
||||
ServerHelper.Error(e2);
|
||||
}
|
||||
// 设置全局
|
||||
Config.GameModuleSupported = supported.Distinct().ToArray();
|
||||
Config.GameModuleSupported = [.. supported.Distinct()];
|
||||
|
||||
return Config.GameModuleSupported.Length > 0;
|
||||
}
|
||||
@ -143,8 +180,8 @@ namespace Milimoe.FunGame.Server.Services
|
||||
try
|
||||
{
|
||||
// 读取plugins目录下的插件
|
||||
Config.ServerPluginLoader = ServerPluginLoader.LoadPlugins(delegates);
|
||||
foreach (ServerPlugin plugin in Config.ServerPluginLoader.Plugins.Values)
|
||||
ServerPluginLoader = ServerPluginLoader.LoadPlugins(delegates);
|
||||
foreach (ServerPlugin plugin in ServerPluginLoader.Plugins.Values)
|
||||
{
|
||||
ServerHelper.WriteLine("Plugin Loaded -> " + plugin.Name, InvokeMessageType.Core);
|
||||
}
|
||||
@ -166,8 +203,8 @@ namespace Milimoe.FunGame.Server.Services
|
||||
try
|
||||
{
|
||||
// 读取plugins目录下的插件
|
||||
Config.WebAPIPluginLoader = WebAPIPluginLoader.LoadPlugins(delegates, otherobjs);
|
||||
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
|
||||
WebAPIPluginLoader = WebAPIPluginLoader.LoadPlugins(delegates, otherobjs);
|
||||
foreach (WebAPIPlugin plugin in WebAPIPluginLoader.Plugins.Values)
|
||||
{
|
||||
ServerHelper.WriteLine("Plugin Loaded -> " + plugin.Name, InvokeMessageType.Core);
|
||||
}
|
||||
@ -194,6 +231,87 @@ namespace Milimoe.FunGame.Server.Services
|
||||
sqlHelper.Execute(RoomQuery.Delete_Rooms(sqlHelper));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化用户密钥列表
|
||||
/// </summary>
|
||||
public static void InitUserKeys()
|
||||
{
|
||||
UserKeys.LoadConfig();
|
||||
UserKeys.SaveConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户的密钥
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUserKey(string username)
|
||||
{
|
||||
if (UserKeys.TryGetValue(username.ToLower(), out object? value) && value is string key)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新指定用户的密钥
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
public static void UpdateUserKey(string username)
|
||||
{
|
||||
UserKeys.Add(username.ToLower(), Encryption.GenerateRandomString());
|
||||
UserKeys.SaveConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 API Secret Key
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
public static string GetAPISecretKey(string token)
|
||||
{
|
||||
using SQLHelper? sql = Factory.OpenFactory.GetSQLHelper();
|
||||
if (sql != null)
|
||||
{
|
||||
sql.ExecuteDataSet(ApiTokens.Select_GetAPIToken(sql, token));
|
||||
if (sql.Result == SQLResult.Success)
|
||||
{
|
||||
return sql.DataSet.Tables[0].Rows[0][ApiTokens.Column_SecretKey].ToString() ?? "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 API Secret Key
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="reference1"></param>
|
||||
/// <param name="reference2"></param>
|
||||
public static void SetAPISecretKey(string token, string reference1 = "", string reference2 = "", SQLHelper? sqlHelper = null)
|
||||
{
|
||||
bool useSQLHelper = sqlHelper != null;
|
||||
sqlHelper ??= Factory.OpenFactory.GetSQLHelper();
|
||||
string key = Encryption.GenerateRandomString();
|
||||
if (sqlHelper != null)
|
||||
{
|
||||
sqlHelper.ExecuteDataSet(ApiTokens.Select_GetAPIToken(sqlHelper, token));
|
||||
if (sqlHelper.Success)
|
||||
{
|
||||
sqlHelper.Execute(ApiTokens.Update_GetAPIToken(sqlHelper, token, key, reference1, reference2));
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlHelper.Execute(ApiTokens.Insert_APITokens(sqlHelper, token, key, reference1, reference2));
|
||||
}
|
||||
}
|
||||
if (!useSQLHelper)
|
||||
{
|
||||
sqlHelper?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 SQL 服务后需要做的事
|
||||
/// </summary>
|
||||
@ -201,10 +319,18 @@ namespace Milimoe.FunGame.Server.Services
|
||||
public static void AfterCreateSQLService(SQLHelper sqlHelper)
|
||||
{
|
||||
Config.SQLMode = sqlHelper.Mode;
|
||||
if (sqlHelper is SQLiteHelper sqliteHelper && !sqliteHelper.DatabaseExists())
|
||||
if (!sqlHelper.DatabaseExists())
|
||||
{
|
||||
ServerHelper.WriteLine("正在初始化数据库 . . .", InvokeMessageType.Core);
|
||||
sqliteHelper.ExecuteSqlFile(AppDomain.CurrentDomain.BaseDirectory + "fungame_sqlite.sql");
|
||||
if (sqlHelper is SQLiteHelper sqliteHelper)
|
||||
{
|
||||
sqliteHelper.ExecuteSqlFile(AppDomain.CurrentDomain.BaseDirectory + "fungame_sqlite.sql");
|
||||
}
|
||||
else if (sqlHelper is MySQLHelper mysqlHelper)
|
||||
{
|
||||
mysqlHelper.ExecuteSqlFile(AppDomain.CurrentDomain.BaseDirectory + "fungame.sql");
|
||||
}
|
||||
SetAPISecretKey(FunGameWebAPITokenID, sqlHelper: sqlHelper);
|
||||
}
|
||||
ServerLogin(sqlHelper);
|
||||
ClearRoomList(sqlHelper);
|
||||
@ -216,23 +342,23 @@ namespace Milimoe.FunGame.Server.Services
|
||||
/// </summary>
|
||||
public static void CloseServer()
|
||||
{
|
||||
if (Config.GameModuleLoader != null)
|
||||
if (GameModuleLoader != null)
|
||||
{
|
||||
foreach (GameModuleServer server in Config.GameModuleLoader.ModuleServers.Values)
|
||||
foreach (GameModuleServer server in GameModuleLoader.ModuleServers.Values)
|
||||
{
|
||||
server.Controller.Close();
|
||||
}
|
||||
}
|
||||
if (Config.ServerPluginLoader != null)
|
||||
if (ServerPluginLoader != null)
|
||||
{
|
||||
foreach (ServerPlugin plugin in Config.ServerPluginLoader.Plugins.Values)
|
||||
foreach (ServerPlugin plugin in ServerPluginLoader.Plugins.Values)
|
||||
{
|
||||
plugin.Controller.Close();
|
||||
}
|
||||
}
|
||||
if (Config.WebAPIPluginLoader != null)
|
||||
if (WebAPIPluginLoader != null)
|
||||
{
|
||||
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
|
||||
foreach (WebAPIPlugin plugin in WebAPIPluginLoader.Plugins.Values)
|
||||
{
|
||||
plugin.Controller.Close();
|
||||
}
|
||||
|
@ -233,12 +233,12 @@ namespace Milimoe.FunGame.Server.Services
|
||||
|
||||
public static void InitOrderList()
|
||||
{
|
||||
Config.OrderList.Clear();
|
||||
Config.OrderList.Add(OrderDictionary.Help, "Milimoe -> 帮助");
|
||||
Config.OrderList.Add(OrderDictionary.Quit, "关闭服务器");
|
||||
Config.OrderList.Add(OrderDictionary.Exit, "关闭服务器");
|
||||
Config.OrderList.Add(OrderDictionary.Close, "关闭服务器");
|
||||
Config.OrderList.Add(OrderDictionary.Restart, "重启服务器");
|
||||
FunGameSystem.OrderList.Clear();
|
||||
FunGameSystem.OrderList.Add(OrderDictionary.Help, "Milimoe -> 帮助");
|
||||
FunGameSystem.OrderList.Add(OrderDictionary.Quit, "关闭服务器");
|
||||
FunGameSystem.OrderList.Add(OrderDictionary.Exit, "关闭服务器");
|
||||
FunGameSystem.OrderList.Add(OrderDictionary.Close, "关闭服务器");
|
||||
FunGameSystem.OrderList.Add(OrderDictionary.Restart, "重启服务器");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
using System.Security.Claims;
|
||||
using System.Data;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
|
||||
using Milimoe.FunGame.Server.Others;
|
||||
using Milimoe.FunGame.Server.Services;
|
||||
using Milimoe.FunGame.WebAPI.Architecture;
|
||||
@ -17,19 +16,21 @@ namespace Milimoe.FunGame.WebAPI.Controllers
|
||||
public class UserController(RESTfulAPIListener apiListener, JWTService jwtTokenService, ILogger<AdapterController> logger) : ControllerBase
|
||||
{
|
||||
[HttpPost("reg")]
|
||||
[Authorize(AuthenticationSchemes = "APIBearer")]
|
||||
public IActionResult Reg([FromBody] RegDTO dto)
|
||||
{
|
||||
// 因为注册 API 不需要先登录,所以需要进行 API Bearer Token 验证,防止 API 滥用
|
||||
// API Bearer Token 保存在数据库 apitokens 表中,由服务器管理员配置
|
||||
try
|
||||
{
|
||||
string clientIP = HttpContext.Connection.RemoteIpAddress?.ToString() + ":" + HttpContext.Connection.RemotePort;
|
||||
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientIP) + " 通过 RESTful API 注册账号 . . .", InvokeMessageType.Core);
|
||||
|
||||
string username = dto.Username;
|
||||
string password = dto.Password;
|
||||
string email = dto.Email;
|
||||
string verifycode = dto.VerifyCode;
|
||||
|
||||
(string msg, RegInvokeType type, bool success) = DataRequestService.Reg(username, password, email, verifycode, clientIP);
|
||||
(string msg, RegInvokeType type, bool success) = DataRequestService.Reg(apiListener, username, password, email, verifycode, clientIP);
|
||||
|
||||
return Ok(new PayloadModel<DataRequestType>()
|
||||
{
|
||||
@ -53,69 +54,85 @@ namespace Milimoe.FunGame.WebAPI.Controllers
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login([FromBody] LoginDTO dto)
|
||||
{
|
||||
Config.ConnectingPlayerCount++;
|
||||
try
|
||||
{
|
||||
PayloadModel<DataRequestType> response = new()
|
||||
{
|
||||
RequestType = DataRequestType.Login_Login
|
||||
};
|
||||
string msg = "用户名或密码不正确。";
|
||||
string msg = "服务器暂时无法处理登录请求。";
|
||||
|
||||
string clientIP = HttpContext.Connection.RemoteIpAddress?.ToString() + ":" + HttpContext.Connection.RemotePort;
|
||||
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientIP) + " 通过 RESTful API 连接至服务器,正在登录 . . .", InvokeMessageType.Core);
|
||||
string username = dto.Username;
|
||||
string password = dto.Password;
|
||||
|
||||
if (apiListener != null)
|
||||
RESTfulAPIModel? model = await CheckConnection(username, clientIP);
|
||||
if (model != null)
|
||||
{
|
||||
// 移除旧模型
|
||||
if (apiListener.UserList.ContainsKey(username))
|
||||
// 预登录
|
||||
(bool success, DataSet dsUser, msg, Guid key) = DataRequestService.PreLogin(this, username, password);
|
||||
if (success)
|
||||
{
|
||||
await apiListener.UserList[username].Send(SocketMessageType.Disconnect);
|
||||
}
|
||||
// 创建新模型
|
||||
if (!apiListener.UserList.ContainsKey(username))
|
||||
{
|
||||
Config.ConnectingPlayerCount++;
|
||||
RESTfulAPIModel model = new(apiListener, clientIP);
|
||||
model.SetClientName(clientIP);
|
||||
// 创建User对象
|
||||
if (model.SQLHelper != null)
|
||||
model.PreLogin(dsUser, key);
|
||||
// 确认登录
|
||||
await model.CheckLogin();
|
||||
string token = jwtTokenService.GenerateToken(username);
|
||||
Config.ConnectingPlayerCount--;
|
||||
response.StatusCode = 200;
|
||||
response.Message = "登录成功!";
|
||||
response.Data = new()
|
||||
{
|
||||
model.SQLHelper.ExecuteDataSet(UserQuery.Select_Users_LoginQuery(model.SQLHelper, username, password));
|
||||
Core.Entity.User user = Factory.GetUser(model.SQLHelper?.DataSet ?? new());
|
||||
if (user.Id != 0)
|
||||
{
|
||||
model.User = user;
|
||||
// 检查有没有重复登录的情况
|
||||
await model.ForceLogOutDuplicateLogonUser();
|
||||
// 添加至玩家列表
|
||||
model.AddUser();
|
||||
model.GetUsersCount();
|
||||
string token = jwtTokenService.GenerateToken(username);
|
||||
Config.ConnectingPlayerCount--;
|
||||
response.StatusCode = 200;
|
||||
response.Message = "登录成功!";
|
||||
response.Data = new()
|
||||
{
|
||||
{ "bearerToken", token },
|
||||
{ "openToken", model.Token }
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
else msg = "服务器暂时无法处理登录请求。";
|
||||
await model.Send(SocketMessageType.Disconnect);
|
||||
{ "bearerToken", token },
|
||||
{ "openToken", model.Token }
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
await model.Send(SocketMessageType.Disconnect);
|
||||
}
|
||||
|
||||
Config.ConnectingPlayerCount--;
|
||||
ServerHelper.WriteLine(msg, InvokeMessageType.Core);
|
||||
response.Message = msg;
|
||||
response.StatusCode = 401;
|
||||
return Unauthorized(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Config.ConnectingPlayerCount--;
|
||||
logger.LogError("Error: {e}", e);
|
||||
}
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
[HttpPost("logout")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> LogOut()
|
||||
{
|
||||
try
|
||||
{
|
||||
PayloadModel<DataRequestType> response = new()
|
||||
{
|
||||
RequestType = DataRequestType.RunTime_Logout
|
||||
};
|
||||
string username = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
|
||||
|
||||
if (apiListener.UserList.ContainsKey(username))
|
||||
{
|
||||
RESTfulAPIModel model = (RESTfulAPIModel)apiListener.UserList[username];
|
||||
await model.Send(SocketMessageType.Disconnect);
|
||||
RevokeToken();
|
||||
model.GetUsersCount();
|
||||
response.Message = "你已成功退出登录! ";
|
||||
response.StatusCode = 200;
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
response.Message = "退出登录失败!";
|
||||
response.StatusCode = 400;
|
||||
return BadRequest(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError("Error: {e}", e);
|
||||
}
|
||||
@ -128,16 +145,12 @@ namespace Milimoe.FunGame.WebAPI.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
string oldToken = HttpContext.Request.Headers.Authorization.ToString().Replace("Bearer ", "");
|
||||
|
||||
// 吊销
|
||||
jwtTokenService.RevokeToken(oldToken);
|
||||
|
||||
// 生成
|
||||
RevokeToken();
|
||||
string username = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
|
||||
string newToken = jwtTokenService.GenerateToken(username);
|
||||
|
||||
return Ok(newToken);
|
||||
if (username.Trim() != "")
|
||||
{
|
||||
return Ok(jwtTokenService.GenerateToken(username));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -145,5 +158,33 @@ namespace Milimoe.FunGame.WebAPI.Controllers
|
||||
}
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
private async Task<RESTfulAPIModel?> CheckConnection(string username, string clientIP)
|
||||
{
|
||||
if (apiListener != null)
|
||||
{
|
||||
// 移除旧模型
|
||||
if (apiListener.UserList.ContainsKey(username))
|
||||
{
|
||||
await apiListener.UserList[username].Send(SocketMessageType.Disconnect);
|
||||
RevokeToken();
|
||||
}
|
||||
// 创建新模型
|
||||
if (!apiListener.UserList.ContainsKey(username))
|
||||
{
|
||||
RESTfulAPIModel model = new(apiListener, clientIP);
|
||||
model.SetClientName(clientIP);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RevokeToken()
|
||||
{
|
||||
// 吊销令牌
|
||||
string oldToken = HttpContext.Request.Headers.Authorization.ToString().Replace("Bearer ", "");
|
||||
if (oldToken.Trim() != "") jwtTokenService.RevokeToken(oldToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,9 @@ try
|
||||
// 读取 Server 插件
|
||||
FunGameSystem.GetServerPlugins();
|
||||
|
||||
// 初始化用户密钥列表
|
||||
FunGameSystem.InitUserKeys();
|
||||
|
||||
// Add services to the container.
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -92,9 +95,9 @@ try
|
||||
Console.WriteLine("\r ");
|
||||
|
||||
// 读取扩展控制器
|
||||
if (Config.WebAPIPluginLoader != null)
|
||||
if (FunGameSystem.WebAPIPluginLoader != null)
|
||||
{
|
||||
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
|
||||
foreach (WebAPIPlugin plugin in FunGameSystem.WebAPIPluginLoader.Plugins.Values)
|
||||
{
|
||||
Assembly? pluginAssembly = Assembly.GetAssembly(plugin.GetType());
|
||||
|
||||
@ -150,7 +153,8 @@ try
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"] ?? "undefined")),
|
||||
NameClaimType = ClaimTypes.NameIdentifier
|
||||
};
|
||||
}).AddScheme<AuthenticationSchemeOptions, CustomBearerAuthenticationHandler>("CustomBearer", options => { });
|
||||
}).AddScheme<AuthenticationSchemeOptions, APIBearerAuthenticationHandler>("APIBearer", options => { }).
|
||||
AddScheme<AuthenticationSchemeOptions, CustomBearerAuthenticationHandler>("CustomBearer", options => { });
|
||||
builder.Logging.AddConsole(options =>
|
||||
{
|
||||
options.FormatterName = "CustomFormatter";
|
||||
|
54
FunGame.WebAPI/Services/APIBearerTokenHandler.cs
Normal file
54
FunGame.WebAPI/Services/APIBearerTokenHandler.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Milimoe.FunGame.Server.Services;
|
||||
|
||||
namespace Milimoe.FunGame.WebAPI.Services
|
||||
{
|
||||
public class APIBearerAuthenticationHandler(IMemoryCache memoryCache, IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder) : AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
|
||||
{
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
// 检查是否有 Authorization Header
|
||||
if (!Request.Headers.TryGetValue("Authorization", out Microsoft.Extensions.Primitives.StringValues value))
|
||||
{
|
||||
return AuthenticateResult.Fail("Authorization header is missing.");
|
||||
}
|
||||
|
||||
string authorizationHeader = value.ToString();
|
||||
if (!authorizationHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return AuthenticateResult.Fail("Invalid Authorization header format.");
|
||||
}
|
||||
|
||||
string token = authorizationHeader["Bearer ".Length..].Trim();
|
||||
|
||||
// 验证 API Bearer Token
|
||||
string key;
|
||||
if (memoryCache.TryGetValue(FunGameSystem.FunGameWebAPITokenID, out object? cacheValue) && cacheValue is string str)
|
||||
{
|
||||
key = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = FunGameSystem.GetAPISecretKey(FunGameSystem.FunGameWebAPITokenID);
|
||||
memoryCache.Set(FunGameSystem.FunGameWebAPITokenID, key, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
if (key == "" || token != key)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return AuthenticateResult.Fail("Invalid Token.");
|
||||
}
|
||||
|
||||
// 如果验证通过,创建 ClaimsIdentity
|
||||
Claim[] claims = [new Claim(ClaimTypes.Name, "FunGame Web API Claim")];
|
||||
ClaimsIdentity identity = new(claims, Scheme.Name);
|
||||
ClaimsPrincipal principal = new(identity);
|
||||
AuthenticationTicket ticket = new(principal, Scheme.Name);
|
||||
|
||||
return AuthenticateResult.Success(ticket);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user