添加 OpenApi 安全方案 (#42)

* 添加 OpenApi 安全方案

* 应用安全方案
This commit is contained in:
yeziuku 2025-01-20 19:22:05 +08:00 committed by GitHub
parent 8dbcb61464
commit 11c3500650
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 72 additions and 31 deletions

View File

@ -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<string, OpenApiSecurityScheme>
{
{
"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<string>()
}
}
];
await Task.CompletedTask;
}
}
}

View File

@ -30,14 +30,14 @@ try
Console.WriteLine(FunGameInfo.GetInfo(Config.FunGameType)); Console.WriteLine(FunGameInfo.GetInfo(Config.FunGameType));
Config.AspNetCore = true; Config.AspNetCore = true;
ServerHelper.WriteLine("正在读取配置文件并初始化服务 . . ."); ServerHelper.WriteLine("正在读取配置文件并初始化服务 . . .");
// 检查是否存在配置文件 // 检查是否存在配置文件
if (!INIHelper.ExistINIFile()) if (!INIHelper.ExistINIFile())
{ {
ServerHelper.WriteLine("未检测到配置文件,将自动创建配置文件 . . ."); ServerHelper.WriteLine("未检测到配置文件,将自动创建配置文件 . . .");
INIHelper.Init(Config.FunGameType); INIHelper.Init(Config.FunGameType);
ServerHelper.WriteLine("配置文件FunGame.ini创建成功请修改该配置文件然后重启服务器。"); ServerHelper.WriteLine("配置文件FunGame.ini创建成功请修改该配置文件然后重启服务器。");
Console.ReadKey(); Console.ReadKey();
return; return;
} }
@ -46,48 +46,48 @@ try
ServerHelper.GetServerSettings(); ServerHelper.GetServerSettings();
} }
// 初始化命令菜单 // 初始化命令菜单
ServerHelper.InitOrderList(); ServerHelper.InitOrderList();
// 初始化SQLHelper // 初始化SQLHelper
FunGameSystem.InitSQLHelper(); FunGameSystem.InitSQLHelper();
// 初始化MailSender // 初始化MailSender
FunGameSystem.InitMailSender(); FunGameSystem.InitMailSender();
// 读取Server插件 // 读取Server插件
FunGameSystem.GetServerPlugins(); FunGameSystem.GetServerPlugins();
// Add services to the container. // Add services to the container.
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
// 读取Web API插件 // 读取Web API插件
object[] otherobjs = [builder]; object[] otherobjs = [builder];
FunGameSystem.GetWebAPIPlugins(otherobjs); FunGameSystem.GetWebAPIPlugins(otherobjs);
// 读取游戏模组 // 读取游戏模组
if (!FunGameSystem.GetGameModuleList()) if (!FunGameSystem.GetGameModuleList())
{ {
ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。"); ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。");
} }
// 创建单例 // 创建单例
RESTfulAPIListener apiListener = new(); RESTfulAPIListener apiListener = new();
RESTfulAPIListener.Instance = apiListener; RESTfulAPIListener.Instance = apiListener;
ServerHelper.WriteLine("请输入 help 来获取帮助,按下 Ctrl+C 关闭服务器。"); ServerHelper.WriteLine("请输入 help 来获取帮助,按下 Ctrl+C 关闭服务器。");
ServerHelper.PrintFunGameTitle(); ServerHelper.PrintFunGameTitle();
if (Config.ServerNotice != "") if (Config.ServerNotice != "")
Console.WriteLine("\r \n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n"); Console.WriteLine("\r \n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n");
else else
Console.WriteLine("无法读取服务器公告"); Console.WriteLine("无法读取服务器公告");
ServerHelper.WriteLine("正在启动 Web API 监听 . . ."); ServerHelper.WriteLine("正在启动 Web API 监听 . . .");
Console.WriteLine("\r "); Console.WriteLine("\r ");
// 读取扩展控制器 // 读取扩展控制器
if (Config.WebAPIPluginLoader != null) if (Config.WebAPIPluginLoader != null)
{ {
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values) foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
@ -96,13 +96,13 @@ try
if (pluginAssembly != null) if (pluginAssembly != null)
{ {
// 注册所有控制器 // 注册所有控制器
builder.Services.AddControllers().PartManager.ApplicationParts.Add(new AssemblyPart(pluginAssembly)); builder.Services.AddControllers().PartManager.ApplicationParts.Add(new AssemblyPart(pluginAssembly));
} }
} }
} }
// 添加 JSON 转换器 // 添加 JSON 转换器
builder.Services.AddControllers().AddJsonOptions(options => builder.Services.AddControllers().AddJsonOptions(options =>
{ {
options.JsonSerializerOptions.WriteIndented = true; options.JsonSerializerOptions.WriteIndented = true;
@ -115,8 +115,11 @@ try
}); });
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApi(); builder.Services.AddOpenApi(options =>
// 添加 CORS 服务 {
options.AddDocumentTransformer(new SecurityDocumentTransformer());
});
// 添加 CORS 服务
builder.Services.AddCors(options => builder.Services.AddCors(options =>
{ {
options.AddPolicy("AllowSpecificOrigin", policy => options.AddPolicy("AllowSpecificOrigin", policy =>
@ -124,7 +127,7 @@ try
policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
}); });
}); });
// 添加 JWT 认证 // 添加 JWT 认证
builder.Services.AddScoped<JWTService>(); builder.Services.AddScoped<JWTService>();
builder.Services.AddAuthentication(options => builder.Services.AddAuthentication(options =>
{ {
@ -152,7 +155,7 @@ try
WebApplication app = builder.Build(); WebApplication app = builder.Build();
// 启用 CORS // 启用 CORS
app.UseCors("AllowSpecificOrigin"); app.UseCors("AllowSpecificOrigin");
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -191,21 +194,21 @@ try
}); });
}); });
// 捕捉关闭程序事件 // 捕捉关闭程序事件
IHostApplicationLifetime lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>(); IHostApplicationLifetime lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>();
lifetime.ApplicationStopping.Register(CloseServer); lifetime.ApplicationStopping.Register(CloseServer);
// 启用 WebSockets 中间件 // 启用 WebSockets 中间件
WebSocketOptions webSocketOptions = new() WebSocketOptions webSocketOptions = new()
{ {
KeepAliveInterval = TimeSpan.FromMinutes(2) // 设置 WebSocket 的保活间隔 KeepAliveInterval = TimeSpan.FromMinutes(2) // 设置 WebSocket 的保活间隔
}; };
app.UseWebSockets(webSocketOptions); app.UseWebSockets(webSocketOptions);
// 路由到 WebSocket 处理器 // 路由到 WebSocket 处理器
app.Map("/ws", WebSocketConnectionHandler); app.Map("/ws", WebSocketConnectionHandler);
// 开始监听连接 // 开始监听连接
listener.BannedList.AddRange(Config.ServerBannedList); listener.BannedList.AddRange(Config.ServerBannedList);
Task order = Task.Factory.StartNew(GetConsoleOrder); Task order = Task.Factory.StartNew(GetConsoleOrder);
@ -252,7 +255,7 @@ async Task WebSocketConnectionHandler(HttpContext context)
bool isConnected = false; bool isConnected = false;
bool isDebugMode = false; bool isDebugMode = false;
// 开始处理客户端连接请求 // 开始处理客户端连接请求
IEnumerable<SocketObject> objs = []; IEnumerable<SocketObject> objs = [];
while (!objs.Any(o => o.SocketType == SocketMessageType.Connect)) while (!objs.Any(o => o.SocketType == SocketMessageType.Connect))
{ {
@ -267,7 +270,7 @@ async Task WebSocketConnectionHandler(HttpContext context)
} }
else else
{ {
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 连接失败。", InvokeMessageType.Core); ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 连接失败。", InvokeMessageType.Core);
await socket.CloseAsync(); await socket.CloseAsync();
} }
Config.ConnectingPlayerCount--; Config.ConnectingPlayerCount--;
@ -280,7 +283,7 @@ async Task WebSocketConnectionHandler(HttpContext context)
catch (Exception e) catch (Exception e)
{ {
if (--Config.ConnectingPlayerCount < 0) Config.ConnectingPlayerCount = 0; if (--Config.ConnectingPlayerCount < 0) Config.ConnectingPlayerCount = 0;
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 中断连接!", InvokeMessageType.Core); ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 中断连接!", InvokeMessageType.Core);
ServerHelper.Error(e); ServerHelper.Error(e);
} }
} }