From 11c3500650dd5f812927807e54564987fe8fbc82 Mon Sep 17 00:00:00 2001 From: yeziuku <53083103+yeziuku@users.noreply.github.com> Date: Mon, 20 Jan 2025 19:22:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20OpenApi=20=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E6=96=B9=E6=A1=88=20(#42)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加 OpenApi 安全方案 * 应用安全方案 --- .../SecurityDocumentTransformer.cs | 38 +++++++++++ FunGame.WebAPI/Program.cs | 65 ++++++++++--------- 2 files changed, 72 insertions(+), 31 deletions(-) create mode 100644 FunGame.WebAPI/Architecture/SecurityDocumentTransformer.cs diff --git a/FunGame.WebAPI/Architecture/SecurityDocumentTransformer.cs b/FunGame.WebAPI/Architecture/SecurityDocumentTransformer.cs new file mode 100644 index 0000000..5852035 --- /dev/null +++ b/FunGame.WebAPI/Architecture/SecurityDocumentTransformer.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.OpenApi; +using Microsoft.OpenApi.Models; + +namespace Milimoe.FunGame.WebAPI.Architecture +{ + public class SecurityDocumentTransformer : IOpenApiDocumentTransformer + { + public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken) + { + document.Components ??= new OpenApiComponents(); + document.Components.SecuritySchemes = new Dictionary + { + { + "Bearer", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.Http, + Scheme = "bearer", + BearerFormat = "JWT", + Description = "BearerToken" + } + } + }; + document.SecurityRequirements = [ + new() + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } + }, + Array.Empty() + } + } + ]; + await Task.CompletedTask; + } + } +} diff --git a/FunGame.WebAPI/Program.cs b/FunGame.WebAPI/Program.cs index 242786f..fc4bef6 100644 --- a/FunGame.WebAPI/Program.cs +++ b/FunGame.WebAPI/Program.cs @@ -30,14 +30,14 @@ try Console.WriteLine(FunGameInfo.GetInfo(Config.FunGameType)); Config.AspNetCore = true; - ServerHelper.WriteLine("ڶȡļʼ . . ."); + ServerHelper.WriteLine("正在读取配置文件并初始化服务 . . ."); - // Ƿļ + // 检查是否存在配置文件 if (!INIHelper.ExistINIFile()) { - ServerHelper.WriteLine("δ⵽ļԶļ . . ."); + ServerHelper.WriteLine("未检测到配置文件,将自动创建配置文件 . . ."); INIHelper.Init(Config.FunGameType); - ServerHelper.WriteLine("ļFunGame.iniɹ޸ĸļȻ"); + ServerHelper.WriteLine("配置文件FunGame.ini创建成功,请修改该配置文件,然后重启服务器。"); Console.ReadKey(); return; } @@ -46,48 +46,48 @@ try ServerHelper.GetServerSettings(); } - // ʼ˵ + // 初始化命令菜单 ServerHelper.InitOrderList(); - // ʼSQLHelper + // 初始化SQLHelper FunGameSystem.InitSQLHelper(); - // ʼMailSender + // 初始化MailSender FunGameSystem.InitMailSender(); - // ȡServer + // 读取Server插件 FunGameSystem.GetServerPlugins(); // Add services to the container. WebApplicationBuilder builder = WebApplication.CreateBuilder(args); - // ȡWeb API + // 读取Web API插件 object[] otherobjs = [builder]; FunGameSystem.GetWebAPIPlugins(otherobjs); - // ȡϷģ + // 读取游戏模组 if (!FunGameSystem.GetGameModuleList()) { - ServerHelper.WriteLine("ƺδװκϷģ飬Ƿȷװǡ"); + ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。"); } - // + // 创建单例 RESTfulAPIListener apiListener = new(); RESTfulAPIListener.Instance = apiListener; - ServerHelper.WriteLine(" help ȡ Ctrl+C رշ"); + ServerHelper.WriteLine("请输入 help 来获取帮助,按下 Ctrl+C 关闭服务器。"); ServerHelper.PrintFunGameTitle(); if (Config.ServerNotice != "") - Console.WriteLine("\r \n********** **********\n\n" + Config.ServerNotice + "\n"); + Console.WriteLine("\r \n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n"); else - Console.WriteLine("޷ȡ"); + Console.WriteLine("无法读取服务器公告"); - ServerHelper.WriteLine(" Web API . . ."); + ServerHelper.WriteLine("正在启动 Web API 监听 . . ."); Console.WriteLine("\r "); - // ȡչ + // 读取扩展控制器 if (Config.WebAPIPluginLoader != null) { foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values) @@ -96,13 +96,13 @@ try if (pluginAssembly != null) { - // עп + // 注册所有控制器 builder.Services.AddControllers().PartManager.ApplicationParts.Add(new AssemblyPart(pluginAssembly)); } } } - // JSON ת + // 添加 JSON 转换器 builder.Services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.WriteIndented = true; @@ -115,8 +115,11 @@ try }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddOpenApi(); - // CORS + builder.Services.AddOpenApi(options => + { + options.AddDocumentTransformer(new SecurityDocumentTransformer()); + }); + // 添加 CORS 服务 builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", policy => @@ -124,7 +127,7 @@ try policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); }); }); - // JWT ֤ + // 添加 JWT 认证 builder.Services.AddScoped(); builder.Services.AddAuthentication(options => { @@ -152,7 +155,7 @@ try WebApplication app = builder.Build(); - // CORS + // 启用 CORS app.UseCors("AllowSpecificOrigin"); // Configure the HTTP request pipeline. @@ -191,21 +194,21 @@ try }); }); - // ׽رճ¼ + // 捕捉关闭程序事件 IHostApplicationLifetime lifetime = app.Services.GetRequiredService(); lifetime.ApplicationStopping.Register(CloseServer); - // WebSockets м + // 启用 WebSockets 中间件 WebSocketOptions webSocketOptions = new() { - KeepAliveInterval = TimeSpan.FromMinutes(2) // WebSocket ı + KeepAliveInterval = TimeSpan.FromMinutes(2) // 设置 WebSocket 的保活间隔 }; app.UseWebSockets(webSocketOptions); - // ·ɵ WebSocket + // 路由到 WebSocket 处理器 app.Map("/ws", WebSocketConnectionHandler); - // ʼ + // 开始监听连接 listener.BannedList.AddRange(Config.ServerBannedList); Task order = Task.Factory.StartNew(GetConsoleOrder); @@ -252,7 +255,7 @@ async Task WebSocketConnectionHandler(HttpContext context) bool isConnected = false; bool isDebugMode = false; - // ʼͻ + // 开始处理客户端连接请求 IEnumerable objs = []; while (!objs.Any(o => o.SocketType == SocketMessageType.Connect)) { @@ -267,7 +270,7 @@ async Task WebSocketConnectionHandler(HttpContext context) } else { - ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " ʧܡ", InvokeMessageType.Core); + ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 连接失败。", InvokeMessageType.Core); await socket.CloseAsync(); } Config.ConnectingPlayerCount--; @@ -280,7 +283,7 @@ async Task WebSocketConnectionHandler(HttpContext context) catch (Exception e) { if (--Config.ConnectingPlayerCount < 0) Config.ConnectingPlayerCount = 0; - ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " жӣ", InvokeMessageType.Core); + ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 中断连接!", InvokeMessageType.Core); ServerHelper.Error(e); } }