添加 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));
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<JWTService>();
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<IHostApplicationLifetime>();
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<SocketObject> 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);
}
}