diff --git a/GameServer/Game/Challenge/ChallengeEntityLoader.cs b/GameServer/Game/Challenge/ChallengeEntityLoader.cs index f4f6bc3e..e898eb7c 100644 --- a/GameServer/Game/Challenge/ChallengeEntityLoader.cs +++ b/GameServer/Game/Challenge/ChallengeEntityLoader.cs @@ -70,10 +70,12 @@ public class ChallengeEntityLoader(SceneInstance scene, PlayerInstance player) : var npcMonsterExcel = GameData.NpcMonsterDataData[challengeMonsterInfo.NpcMonsterId]; // Create monster from group monster info - var entity = new EntityMonster(scene, info.ToPositionProto(), info.ToRotationProto(), group.Id, info.ID, - npcMonsterExcel, info); - entity.EventID = challengeMonsterInfo.EventId; - entity.CustomStageID = challengeMonsterInfo.EventId; + var entity = new EntityMonster(Scene, info.ToPositionProto(), info.ToRotationProto(), group.Id, info.ID, + npcMonsterExcel, info) + { + EventID = challengeMonsterInfo.EventId, + CustomStageID = challengeMonsterInfo.EventId + }; await Scene.AddEntity(entity, sendPacket); return entity; diff --git a/GameServer/Game/Mission/FinishAction/Handler/MissionHandlerEnterEntryIfNotThere.cs b/GameServer/Game/Mission/FinishAction/Handler/MissionHandlerEnterEntryIfNotThere.cs index a2adca8b..6328ff07 100644 --- a/GameServer/Game/Mission/FinishAction/Handler/MissionHandlerEnterEntryIfNotThere.cs +++ b/GameServer/Game/Mission/FinishAction/Handler/MissionHandlerEnterEntryIfNotThere.cs @@ -1,7 +1,5 @@ -using EggLink.DanhengServer.Enums; -using EggLink.DanhengServer.Enums.Mission; +using EggLink.DanhengServer.Enums.Mission; using EggLink.DanhengServer.GameServer.Game.Player; -using EggLink.DanhengServer.Proto; namespace EggLink.DanhengServer.GameServer.Game.Mission.FinishAction.Handler; @@ -14,6 +12,6 @@ public class MissionHandlerEnterEntryIfNotThere : MissionFinishActionHandler var anchorGroup = Params[1]; var anchorId = Params[2]; - await Player.EnterMissionScene(entryId, anchorGroup, anchorId, true, ChangeStoryLineAction.FinishAction); + await Player.EnterMissionScene(entryId, anchorGroup, anchorId, true); } } \ No newline at end of file diff --git a/WebServer/Controllers/MuipServerRoutes.cs b/WebServer/Controllers/MuipServerRoutes.cs index 9df0273f..4746d61b 100644 --- a/WebServer/Controllers/MuipServerRoutes.cs +++ b/WebServer/Controllers/MuipServerRoutes.cs @@ -11,14 +11,18 @@ namespace EggLink.DanhengServer.WebServer.Controllers; [Route("/")] public class MuipServerRoutes { + [HttpPost("/muip/create_session")] + public IActionResult CreateSession([FromBody] CreateSessionRequestBody req) + { + var resp = MuipManager.CreateSession(req.key_type); + return new JsonResult(resp); + } + [HttpPost("/muip/auth_admin")] public IActionResult AuthAdminKey([FromBody] AuthAdminKeyRequestBody req) { - var data = MuipManager.AuthAdminAndCreateSession(req.admin_key, req.key_type); - if (data == null) - return new JsonResult(new AuthAdminKeyResponse(1, "Admin key is invalid or the function is not enabled!", - null)); - return new JsonResult(new AuthAdminKeyResponse(0, "Authorized admin key successfully!", data)); + var resp = MuipManager.AuthAdmin(req.session_id, req.admin_key); + return new JsonResult(resp); } [HttpGet("/muip/exec_cmd")] diff --git a/WebServer/Request/AuthRequest.cs b/WebServer/Request/AuthRequest.cs index 74db3eb0..2da42707 100644 --- a/WebServer/Request/AuthRequest.cs +++ b/WebServer/Request/AuthRequest.cs @@ -2,6 +2,6 @@ public class AuthAdminKeyRequestBody { + public string session_id { get; set; } = ""; public string admin_key { get; set; } = ""; - public string key_type { get; set; } = "XML"; } \ No newline at end of file diff --git a/WebServer/Request/CreateSessionRequest.cs b/WebServer/Request/CreateSessionRequest.cs new file mode 100644 index 00000000..db693bf3 --- /dev/null +++ b/WebServer/Request/CreateSessionRequest.cs @@ -0,0 +1,6 @@ +namespace EggLink.DanhengServer.WebServer.Request; + +public class CreateSessionRequestBody +{ + public string key_type { get; set; } = "XML"; +} \ No newline at end of file diff --git a/WebServer/Response/AuthAdminKeyResponse.cs b/WebServer/Response/AuthAdminKeyResponse.cs index 0e7f3be2..2a52eed1 100644 --- a/WebServer/Response/AuthAdminKeyResponse.cs +++ b/WebServer/Response/AuthAdminKeyResponse.cs @@ -7,7 +7,6 @@ public class AuthAdminKeyResponse(int code, string message, AuthAdminKeyData? da public class AuthAdminKeyData { - public string RsaPublicKey { get; set; } = ""; public string SessionId { get; set; } = ""; public long ExpireTimeStamp { get; set; } = 0; } \ No newline at end of file diff --git a/WebServer/Response/CreateSessionResponse.cs b/WebServer/Response/CreateSessionResponse.cs new file mode 100644 index 00000000..50bf206b --- /dev/null +++ b/WebServer/Response/CreateSessionResponse.cs @@ -0,0 +1,13 @@ +namespace EggLink.DanhengServer.WebServer.Response; + +public class CreateSessionResponse(int code, string message, CreateSessionData? data) + : BaseResponse(code, message, data) +{ +} + +public class CreateSessionData +{ + public string RsaPublicKey { get; set; } = ""; + public string SessionId { get; set; } = ""; + public long ExpireTimeStamp { get; set; } = 0; +} \ No newline at end of file diff --git a/WebServer/Server/MuipManager.cs b/WebServer/Server/MuipManager.cs index 44cebe3e..2aa4cb4f 100644 --- a/WebServer/Server/MuipManager.cs +++ b/WebServer/Server/MuipManager.cs @@ -15,6 +15,7 @@ using EggLink.DanhengServer.WebServer.Response; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.X509; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace EggLink.DanhengServer.WebServer.Server; @@ -37,11 +38,9 @@ public static class MuipManager public static event ServerInformationDelegate? OnGetServerInformation; public static event GetPlayerStatusDelegate? OnGetPlayerStatus; - public static AuthAdminKeyData? AuthAdminAndCreateSession(string key, string key_type) + public static CreateSessionResponse CreateSession(string keyType) { - if (ConfigManager.Config.MuipServer.AdminKey == "" || - ConfigManager.Config.MuipServer.AdminKey != key) return null; - + if (ConfigManager.Config.MuipServer.AdminKey == "") return new CreateSessionResponse(1, "This function is not enabled in this server!", null); var session = new MuipSession { SessionId = Guid.NewGuid().ToString(), @@ -50,20 +49,62 @@ public static class MuipManager IsAdmin = true }; - if (key_type == "PEM") + if (keyType == "PEM") // convert to PEM session.RsaPublicKey = XMLToPEM_Pub(session.RsaPublicKey); Sessions.Add(session.SessionId, session); - var data = new AuthAdminKeyData + var data = new CreateSessionData() { RsaPublicKey = session.RsaPublicKey, SessionId = session.SessionId, ExpireTimeStamp = session.ExpireTimeStamp }; - return data; + return new CreateSessionResponse(0, "Created!", data); + } + + public static AuthAdminKeyResponse AuthAdmin(string sessionId, string key) + { + if (Sessions.TryGetValue(sessionId, out var value)) + { + var session = value; + if (session.ExpireTimeStamp < DateTime.Now.ToUnixSec()) + { + Sessions.Remove(sessionId); + return new AuthAdminKeyResponse(1, "Session has expired!", null); + } + // decrypt key + var rsa = new RSACryptoServiceProvider(); + rsa.FromXmlString(GetRsaKeyPair().Item2); // private key + byte[] decrypted; + + try + { + decrypted = rsa.Decrypt(Convert.FromBase64String(key), RSAEncryptionPadding.Pkcs1); + } + catch + { + return new AuthAdminKeyResponse(3, "Wrong encrypted key", null); + } + + var keyStr = Encoding.UTF8.GetString(decrypted); + if (keyStr != ConfigManager.Config.MuipServer.AdminKey) + return new AuthAdminKeyResponse(2, "Admin key is invalid!", null); + + session.IsAuthorized = true; + + var data = new AuthAdminKeyData + { + SessionId = session.SessionId, + ExpireTimeStamp = session.ExpireTimeStamp + }; + + return new AuthAdminKeyResponse(0, "Authorized admin key successfully!", data); + } + + return new AuthAdminKeyResponse(4, "Session not found!", null); } public static MuipSession? GetSession(string sessionId) @@ -94,6 +135,9 @@ public static class MuipManager return new ExecuteCommandResponse(1, "Session has expired!"); } + if (!session.IsAuthorized) + return new ExecuteCommandResponse(4, "Not authorized!"); + var rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(GetRsaKeyPair().Item2); byte[] decrypted; @@ -139,6 +183,8 @@ public static class MuipManager Sessions.Remove(sessionId); return new ServerInformationResponse(1, "Session has expired!"); } + if (!session.IsAuthorized) + return new ServerInformationResponse(3, "Not authorized!"); var currentProcess = Process.GetCurrentProcess(); @@ -191,8 +237,9 @@ public static class MuipManager Sessions.Remove(sessionId); return new PlayerInformationResponse(1, "Session has expired!"); } + if (!session.IsAuthorized) + return new PlayerInformationResponse(4, "Not authorized!"); - var result = new Dictionary(); var player = DatabaseHelper.Instance?.GetInstance(uid); if (player == null) return new PlayerInformationResponse(2, "Player not exist!"); diff --git a/WebServer/Server/MuipSession.cs b/WebServer/Server/MuipSession.cs index 9053d399..e295a0ef 100644 --- a/WebServer/Server/MuipSession.cs +++ b/WebServer/Server/MuipSession.cs @@ -9,5 +9,6 @@ public class MuipSession public long ExpireTimeStamp { get; set; } = 0; public bool IsAdmin { get; set; } = false; + public bool IsAuthorized { get; set; } = false; public AccountData? Account { get; set; } = null; } \ No newline at end of file diff --git a/docs/MuipAPI_zh-CN.md b/docs/MuipAPI_zh-CN.md index ccd8e42a..3a12ff6d 100644 --- a/docs/MuipAPI_zh-CN.md +++ b/docs/MuipAPI_zh-CN.md @@ -2,15 +2,14 @@ ## 💡API帮助 - 自2.3版本开始,支持外部API调用接口 -- 总接口为Dispatch接口加上入口,比如你的Dispatch为 http://127.0.0.1:8080,请求参数和返回都为json格式 -- (1)授权接口: http://127.0.0.1:8080/muip/auth_admin (支持POST) - - -必传参数1:admin_key (在config.php的MuipServer/AdminKey配置) - - -必传参数2:key_type (类型,比如PEM) +- 总接口为Dispatch接口加上入口,比如你的Dispatch为 http://127.0.0.1:8080 ,请求参数和返回都为json格式 +- (1)创建会话接口: http://127.0.0.1:8080/muip/create_session (支持POST) + - -可选参数:key_type (类型,仅支持PEM或默认XML) - -返回示例: ```json { "code": 0, - "message": "Authorized admin key successfully!", + "message": "Created!", "data": { "rsaPublicKey": "***", "sessionId": "***", @@ -18,9 +17,23 @@ } } ``` -- (2)提交命令接口: http://127.0.0.1:8080/muip/exec_cmd (支持POST/GET) - - -必传参数1:SessionId (在授权接口请求后获得) - - -必传参数2:Command (需要执行的命令经过rsaPublicKey[授权接口获取]下RSA[pacs#1]加密) +- (2)授权接口: http://127.0.0.1:8080/muip/auth_admin (支持POST) + - -必传参数1:SessionId (在创建会话接口请求后获得) + - -必传参数2:admin_key (在config.json的MuipServer.AdminKey配置,并且经过rsaPublicKey[创建会话接口获取]下RSA[pacs#1]加密) + - -返回示例: + ```json + { + "code": 0, + "message": "Authorized admin key successfully!", + "data": { + "sessionId": "***", + "expireTimeStamp": *** + } + } + ``` +- (3)提交命令接口: http://127.0.0.1:8080/muip/exec_cmd (支持POST/GET) + - -必传参数1:SessionId (在创建会话接口请求后获得) + - -必传参数2:Command (需要执行的命令经过rsaPublicKey[创建会话接口获取]下RSA[pacs#1]加密) - -必传参数3:TargetUid (执行命令的玩家UID) - -返回示例: ```json @@ -33,8 +46,8 @@ } } ``` -- (3)获取服务器状态接口: http://127.0.0.1:8080/muip/server_information (支持POST/GET) - - -必传参数1:SessionId (在授权接口请求后获得) +- (4)获取服务器状态接口: http://127.0.0.1:8080/muip/server_information (支持POST/GET) + - -必传参数1:SessionId (在创建会话接口请求后获得) - -返回示例: ```json { @@ -56,8 +69,8 @@ } } ``` -- (4)获取玩家信息接口: http://127.0.0.1:8080/muip/player_information (支持POST/GET) - - -必传参数1:SessionId (在授权接口请求后获得) +- (5)获取玩家信息接口: http://127.0.0.1:8080/muip/player_information (支持POST/GET) + - -必传参数1:SessionId (在创建会话接口请求后获得) - -必传参数2:Uid (玩家UID) - -返回示例: ```json