You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
598 lines
27 KiB
598 lines
27 KiB
using AspNetCoreRateLimit; |
|
using ATS.NonCustodial.AdminUi.Attributes; |
|
using ATS.NonCustodial.AdminUi.Auth; |
|
using ATS.NonCustodial.AdminUi.Extensions; |
|
using ATS.NonCustodial.AdminUi.Extensions.Host; |
|
using ATS.NonCustodial.AdminUi.Extensions.ImSignalR; |
|
using ATS.NonCustodial.AdminUi.Filters; |
|
using ATS.NonCustodial.AdminUi.Helpers; |
|
using ATS.NonCustodial.AdminUi.Helpers.Logs; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.IM.Notifies; |
|
using ATS.NonCustodial.Application.Impl.Business.IM; |
|
using ATS.NonCustodial.DynamicApi; |
|
using ATS.NonCustodial.Shared.Common.Auth; |
|
using ATS.NonCustodial.Shared.Common.Constants; |
|
using ATS.NonCustodial.Shared.Common.Enums; |
|
using ATS.NonCustodial.Shared.Tools.Cache; |
|
using IdentityServer4.AccessTokenValidation; |
|
using Microsoft.AspNetCore.Authentication; |
|
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|
using Microsoft.AspNetCore.Builder; |
|
using Microsoft.AspNetCore.Hosting; |
|
using Microsoft.AspNetCore.Http; |
|
using Microsoft.AspNetCore.Http.Connections; |
|
using Microsoft.AspNetCore.HttpOverrides; |
|
using Microsoft.AspNetCore.Mvc.Controllers; |
|
using Microsoft.AspNetCore.SignalR; |
|
using Microsoft.Extensions.Configuration; |
|
using Microsoft.Extensions.DependencyInjection; |
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
|
using Microsoft.Extensions.DependencyModel; |
|
using Microsoft.Extensions.Hosting; |
|
using Microsoft.IdentityModel.Tokens; |
|
using Microsoft.OpenApi.Any; |
|
using Microsoft.OpenApi.Models; |
|
using Newtonsoft.Json; |
|
using Newtonsoft.Json.Serialization; |
|
using Serilog; |
|
using System.IdentityModel.Tokens.Jwt; |
|
using System.Reflection; |
|
using System.Text; |
|
using ATS.NonCustodial.Shared.Helpers.Http.HttpPolly; |
|
using Yitter.IdGenerator; |
|
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration; |
|
|
|
namespace ATS.NonCustodial.AdminUi.Configurations |
|
{ |
|
/// <summary> |
|
/// Startup==> ServiceCollection 注入扩展 |
|
/// </summary> |
|
/// Author:mxg |
|
/// CreatedTimed:2022-05-30 08:57 PM |
|
public static class AdminServerCollectionExtension |
|
{ |
|
/// <summary> |
|
/// This method gets called by the runtime. Use this method to add services to the container. |
|
/// </summary> |
|
/// <param name="services"></param> |
|
/// <param name="adminUiOptions"></param> |
|
/// <param name="configuration"></param> |
|
/// <param name="assemblies"></param> |
|
public static void AddAdminServices(this IServiceCollection services, AdminUiOptions adminUiOptions, IConfiguration configuration, Assembly[] assemblies) |
|
{ |
|
//雪花漂移算法 |
|
YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1) { WorkerIdBitLength = 6 }); |
|
|
|
//权限处理 |
|
services.AddScoped<IPermissionHandler, PermissionHandler>(); |
|
services.AddScoped<IHttpPollyHelper, HttpPollyHelper>(); |
|
|
|
// ClaimType不被更改 |
|
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); |
|
|
|
//用户信息 |
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
|
if (adminUiOptions.IdentityServerConfiguration.Enable) services.TryAddSingleton<IUser, UserIdentityServer>(); //is4 |
|
else services.TryAddSingleton<IUser, User>(); //jwt |
|
|
|
//AutoMapper映射配置 |
|
services.AddAutoMapper((serviceProvider, cfg) => |
|
{ |
|
// 你可以在这里进行全局性的配置 |
|
cfg.AllowNullCollections = true; // 示例:允许空集合映射 |
|
|
|
// 如果你需要从服务提供器(IServiceProvider)解析服务,以便在映射配置中使用,可以使用 serviceProvider 参数 |
|
// var someService = serviceProvider.GetRequiredService<ISomeService>(); |
|
// cfg.ConstructServicesUsing(type => serviceProvider.GetService(type)); // 另一种设置服务构造函数的方法 |
|
}, assemblies); |
|
|
|
//注册job |
|
services.InitialQuartzJob(adminUiOptions); |
|
|
|
//Cors 跨域 |
|
services.AddAdminApiCors(adminUiOptions); |
|
|
|
//个推 |
|
services.AddSingleton(adminUiOptions.TweetsConfigConfiguration); |
|
services.AddSingleton(adminUiOptions.SmsConfiguration); |
|
|
|
#region 身份认证授权 |
|
|
|
//signalR:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0 |
|
var jwtConfig = adminUiOptions.JwtConfiguration; |
|
services.TryAddSingleton(jwtConfig); |
|
if (adminUiOptions.IdentityServerConfiguration.Enable) |
|
{ |
|
//is4 |
|
services.AddAuthentication(options => |
|
{ |
|
options.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme; |
|
options.DefaultChallengeScheme = nameof(ResponseAuthenticationHandler); //401 |
|
options.DefaultForbidScheme = nameof(ResponseAuthenticationHandler); //403 |
|
}) |
|
.AddJwtBearer(options => |
|
{ |
|
options.Authority = adminUiOptions.IdentityServerConfiguration.Url; |
|
options.RequireHttpsMetadata = false; |
|
options.Audience = "ATS.NonCustodial.Admin.Api"; |
|
|
|
//重点在于这里;判断是SignalR的路径 |
|
options.Events = new JwtBearerEvents |
|
{ |
|
OnMessageReceived = (context) => |
|
{ |
|
if (!context.HttpContext.Request.Path.HasValue) return Task.CompletedTask; |
|
|
|
//重点在于这里;判断是SignalR的路径 |
|
var accessToken = context.HttpContext.Request.Query["access_token"]; |
|
var path = context.HttpContext.Request.Path; |
|
if (string.IsNullOrWhiteSpace(accessToken) || !path.StartsWithSegments("/nonCustodialHub")) return Task.CompletedTask; |
|
|
|
context.Token = accessToken; |
|
return Task.CompletedTask; |
|
} |
|
}; |
|
}) |
|
.AddScheme<AuthenticationSchemeOptions, ResponseAuthenticationHandler>(nameof(ResponseAuthenticationHandler), o => { }); |
|
} |
|
else |
|
{ |
|
//jwt |
|
services.AddAuthentication(options => |
|
{ |
|
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; |
|
options.DefaultChallengeScheme = nameof(ResponseAuthenticationHandler); //401 |
|
options.DefaultForbidScheme = nameof(ResponseAuthenticationHandler); //403 |
|
}) |
|
.AddJwtBearer(options => |
|
{ |
|
options.TokenValidationParameters = new TokenValidationParameters |
|
{ |
|
ValidateIssuer = true, |
|
ValidateAudience = true, |
|
ValidateLifetime = true, |
|
ValidateIssuerSigningKey = true, |
|
ValidIssuer = jwtConfig.Issuer, |
|
ValidAudience = jwtConfig.Audience, |
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SymmetricSecurityKey)), |
|
ClockSkew = TimeSpan.Zero |
|
}; |
|
|
|
//重点在于这里;判断是SignalR的路径(https://www.cnblogs.com/fger/p/11811190.html) |
|
options.Events = new JwtBearerEvents |
|
{ |
|
OnMessageReceived = (context) => |
|
{ |
|
if (!context.HttpContext.Request.Path.HasValue) return Task.CompletedTask; |
|
|
|
//重点在于这里;判断是SignalR的路径 |
|
var accessToken = context.HttpContext.Request.Query["access_token"]; |
|
var path = context.HttpContext.Request.Path; |
|
if (string.IsNullOrWhiteSpace(accessToken) || !path.StartsWithSegments("/nonCustodialHub")) return Task.CompletedTask; |
|
|
|
context.Token = accessToken; |
|
return Task.CompletedTask; |
|
}, |
|
|
|
//此处为权限验证失败后触发的事件 |
|
OnChallenge = context => |
|
{ |
|
//此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦,必须 |
|
context.HandleResponse(); |
|
//自定义自己想要返回的数据结果,我这里要返回的是Json对象,通过引用Newtonsoft.Json库进行转换 |
|
var payload = new { StatusCode = 0, Message = "身份认证失败!" }; |
|
//自定义返回的数据类型 |
|
context.Response.ContentType = "application/json"; |
|
//自定义返回状态码,默认为401 我这里改成 200 |
|
context.Response.StatusCode = StatusCodes.Status200OK; |
|
//context.Response.StatusCode = StatusCodes.Status401Unauthorized; |
|
//输出Json数据结果 |
|
context.Response.WriteAsync(Convert.ToString(payload)); |
|
return Task.FromResult(0); |
|
} |
|
}; |
|
}) |
|
.AddScheme<AuthenticationSchemeOptions, ResponseAuthenticationHandler>(nameof(ResponseAuthenticationHandler), o => { }); |
|
} |
|
|
|
#endregion 身份认证授权 |
|
|
|
#region Swagger Api文档 |
|
|
|
if (adminUiOptions.SwaggerConfiguration.Enable) |
|
{ |
|
services.AddSwaggerGen(options => |
|
{ |
|
typeof(ApiVersionEnum).GetEnumNames().ToList().ForEach(version => |
|
{ |
|
options.SwaggerDoc(version, new OpenApiInfo |
|
{ |
|
Version = version, |
|
Title = "ATS.NonCustodial.Admin.Api" |
|
}); |
|
//c.OrderActionsBy(o => o.RelativePath); |
|
}); |
|
|
|
options.SchemaFilter<EnumSchemaFilter>(); |
|
|
|
options.CustomOperationIds(apiDesc => |
|
{ |
|
var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor; |
|
return controllerAction?.ControllerName + "-" + controllerAction?.ActionName; |
|
}); |
|
|
|
options.ResolveConflictingActions(apiDescription => apiDescription.First()); |
|
options.CustomSchemaIds(x => x.FullName); |
|
options.DocInclusionPredicate((docName, description) => true); |
|
|
|
var xmlFiles = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "xml"), "*.xml"); |
|
if (xmlFiles.Length > 0) |
|
{ |
|
foreach (var xmlFile in xmlFiles) |
|
{ |
|
options.IncludeXmlComments(xmlFile, true); |
|
} |
|
} |
|
|
|
var server = new OpenApiServer() |
|
{ |
|
Url = adminUiOptions.SwaggerConfiguration.Url, |
|
Description = "" |
|
}; |
|
server.Extensions.Add("extensions", new OpenApiObject |
|
{ |
|
["copyright"] = new OpenApiString(adminUiOptions.SwaggerConfiguration.Footer) |
|
}); |
|
|
|
//options.AddServer(server); |
|
|
|
#region 添加设置Token的按钮 |
|
|
|
if (adminUiOptions.IdentityServerConfiguration.Enable) |
|
{ |
|
//添加Jwt验证设置 |
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement() |
|
{ |
|
{ |
|
new OpenApiSecurityScheme |
|
{ |
|
Reference = new OpenApiReference |
|
{ |
|
Id = "oauth2", |
|
Type = ReferenceType.SecurityScheme |
|
} |
|
}, |
|
new List<string>() |
|
} |
|
}); |
|
|
|
//统一认证 |
|
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme |
|
{ |
|
Type = SecuritySchemeType.OAuth2, |
|
Description = "oauth2登录授权", |
|
Flows = new OpenApiOAuthFlows |
|
{ |
|
Implicit = new OpenApiOAuthFlow |
|
{ |
|
AuthorizationUrl = new Uri($"{adminUiOptions.IdentityServerConfiguration.Url}/connect/authorize"), |
|
Scopes = new Dictionary<string, string> |
|
{ |
|
{ "ATS.NonCustodial.Admin.Api", "ATS.NonCustodial.Admin.Api" } |
|
} |
|
}, |
|
//AuthorizationCode = new OpenApiOAuthFlow |
|
//{ |
|
// AuthorizationUrl = new Uri($"{adminApiConfiguration.IdentityServerBaseUrl}/connect/authorize"), |
|
// TokenUrl = new Uri($"{adminApiConfiguration.IdentityServerBaseUrl}/connect/token"), |
|
// Scopes = new Dictionary<string, string> { |
|
// { |
|
// adminApiConfiguration.OidcApiName, adminApiConfiguration.ApiName } |
|
// } |
|
//} |
|
} |
|
}); |
|
options.OperationFilter<AuthorizeCheckOperationFilter>(); |
|
} |
|
else |
|
{ |
|
//添加Jwt验证设置 |
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement() |
|
{ |
|
{ |
|
new OpenApiSecurityScheme |
|
{ |
|
Reference = new OpenApiReference |
|
{ |
|
Id = "Bearer", |
|
Type = ReferenceType.SecurityScheme |
|
} |
|
}, |
|
new List<string>() |
|
} |
|
}); |
|
|
|
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
|
{ |
|
Description = "Value: Bearer {token}", |
|
Name = "Authorization", |
|
In = ParameterLocation.Header, |
|
Type = SecuritySchemeType.ApiKey |
|
}); |
|
} |
|
|
|
#endregion 添加设置Token的按钮 |
|
|
|
//注册Api过滤器 |
|
options.DocumentFilter<ApiToSwaggerFilter>(); |
|
}); |
|
} |
|
|
|
#endregion Swagger Api文档 |
|
|
|
//操作日志 |
|
if (adminUiOptions.LogConfiguration.EnableOperationLog) services.AddScoped<ILogHandler, LogHandler>(); |
|
|
|
#region 控制器 |
|
|
|
services.AddControllers(options => |
|
{ |
|
options.Filters.Add<ControllerExceptionFilter>(); |
|
options.Filters.Add<ValidateInputFilter>(); |
|
options.Filters.Add<ValidatePermissionAttribute>(); |
|
if (adminUiOptions.LogConfiguration.EnableOperationLog) |
|
{ |
|
options.Filters.Add<ControllerLogFilter>(); |
|
} |
|
//禁止去除ActionAsync后缀 |
|
//options.SuppressAsyncSuffixInActionNames = false; |
|
}) |
|
//.AddFluentValidation(config => |
|
//{ |
|
// var assembly = Assembly.LoadFrom(Path.Combine(basePath, "ATS.NonCustodial.Admin.dll")); |
|
// config.RegisterValidatorsFromAssembly(assembly); |
|
//}) |
|
.AddNewtonsoftJson(options => |
|
{ |
|
//忽略循环引用 |
|
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; |
|
//使用驼峰 首字母小写 |
|
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); |
|
//设置时间格式 |
|
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; |
|
}) |
|
.AddControllersAsServices(); |
|
|
|
#endregion 控制器 |
|
|
|
services.AddHttpClient(); |
|
|
|
#region 缓存 |
|
|
|
var cacheConfig = adminUiOptions.CacheConfiguration; |
|
if (cacheConfig.Type == CacheTypeEnum.Redis) |
|
{ |
|
var csredis = new CSRedis.CSRedisClient(cacheConfig.Redis.ConnectionString); |
|
RedisHelper.Initialization(csredis); |
|
services.AddSingleton<ICacheTool, RedisCacheTool>(); |
|
} |
|
else |
|
{ |
|
services.AddMemoryCache(); |
|
services.AddSingleton<ICacheTool, MemoryCacheTool>(); |
|
} |
|
|
|
#endregion 缓存 |
|
|
|
#region singalR |
|
|
|
// Change to use Name as the user identifier for SignalR |
|
// WARNING: This requires that the source of your JWT token |
|
// ensures that the Name claim is unique! |
|
// If the Name claim isn't unique, users could receive messages |
|
// intended for a different user! |
|
services.AddSingleton<IUserIdProvider, NameUserIdProvider>(); |
|
|
|
//SignalR https://docs.microsoft.com/zh-cn/aspnet/core/signalr/configuration?view=aspnetcore-6.0&tabs=dotnet |
|
services |
|
.AddSignalR() |
|
.AddHubOptions<NonCustodialHub>(options => |
|
{ |
|
const int keepAliveIntervalInSeconds = 60; |
|
options.EnableDetailedErrors = true; |
|
//客户端发保持连接请求到服务端最长间隔,默认30秒 |
|
options.ClientTimeoutInterval = TimeSpan.FromSeconds(2 * keepAliveIntervalInSeconds); |
|
options.HandshakeTimeout = TimeSpan.FromSeconds(keepAliveIntervalInSeconds); |
|
//服务端发保持连接请求到客户端间隔,默认15秒 |
|
options.KeepAliveInterval = TimeSpan.FromSeconds(keepAliveIntervalInSeconds); |
|
}) |
|
.AddJsonProtocol(options => |
|
{ |
|
options.PayloadSerializerOptions.PropertyNamingPolicy = null; |
|
}); |
|
services.AddSingleton(typeof(IClientNotifyService), typeof(ClientNotifyService)); |
|
|
|
#endregion singalR |
|
|
|
//性能分析 (https://miniprofiler.com/) |
|
//默认的index.html页面可以从如下链接下载 |
|
//https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerUI/index.html |
|
if (adminUiOptions.SwaggerConfiguration.EnableMiniProfiler) services.AddMiniProfiler();//AddComtorizedMiniProfiler(); |
|
|
|
//动态api |
|
services.AddDynamicApi(options => |
|
{ |
|
var assemblies = DependencyContext.Default.RuntimeLibraries |
|
.Where(a => a.Name.EndsWith("Service")) |
|
.Select(o => Assembly.Load(new AssemblyName(o.Name))).ToArray(); |
|
options.AddAssemblyOptions(assemblies); |
|
}); |
|
} |
|
|
|
/// <summary> |
|
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. |
|
/// </summary> |
|
/// <param name="app"></param> |
|
/// <param name="env"></param> |
|
/// <param name="adminUiOptions"></param> |
|
/// <param name="indexStream"></param> |
|
public static void ConfigApp(IApplicationBuilder app, IWebHostEnvironment env, AdminUiOptions adminUiOptions, Stream? indexStream) |
|
{ |
|
//IP限流 |
|
if (adminUiOptions.RateLimitConfiguration.Enable) app.UseIpRateLimiting(); |
|
|
|
if (env.IsDevelopment()) |
|
{ |
|
app.UseDeveloperExceptionPage(); |
|
} |
|
else |
|
{ |
|
app.UseExceptionHandler("/Error"); |
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. |
|
app.UseHsts(); |
|
} |
|
|
|
//静态文件 |
|
app.UseDefaultFiles(); |
|
|
|
app.UseHttpsRedirection(); |
|
app.UseStaticFiles(); |
|
app.UseUploadConfig(); |
|
|
|
//激活中间件,启用MiniProfiler服务,放在UseEndpoints方法之前 |
|
if (adminUiOptions.SwaggerConfiguration.EnableMiniProfiler) app.UseMiniProfiler(); |
|
//路由 |
|
app.UseRouting(); |
|
|
|
//跨域 |
|
app.UseCors(AdminConstant.requestPolicyName); |
|
|
|
//认证 |
|
app.UseAuthentication(); |
|
|
|
//授权 |
|
app.UseAuthorization(); |
|
|
|
//配置端点(include signalR) |
|
app.UseEndpoints(endpoints => |
|
{ |
|
endpoints.MapControllers(); |
|
|
|
//即时通讯 |
|
endpoints.MapHub<NonCustodialHub>("/nonCustodialHub", options => |
|
{ |
|
options.Transports = |
|
HttpTransportType.WebSockets | |
|
HttpTransportType.LongPolling; |
|
options.LongPolling.PollTimeout = TimeSpan.FromSeconds(30); |
|
}).RequireCors(t => |
|
t.WithOrigins(adminUiOptions.UrlsConfiguration.CorUrls.Any() |
|
? adminUiOptions.UrlsConfiguration.CorUrls.ToArray() |
|
: new string[] { }) |
|
.AllowAnyMethod() |
|
.AllowAnyHeader() |
|
.AllowCredentials() |
|
); |
|
}); |
|
|
|
//解决Ubuntu下Nginx代理不能获取IP问题 |
|
app.UseForwardedHeaders(new ForwardedHeadersOptions |
|
{ |
|
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto |
|
}); |
|
|
|
#region Swagger Api文档 |
|
|
|
if (!env.IsDevelopment() && !adminUiOptions.SwaggerConfiguration.Enable) return; |
|
|
|
app.UseSwagger(); |
|
app.UseSwaggerUI(c => |
|
{ |
|
typeof(ApiVersionEnum).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version => |
|
{ |
|
c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"ATS.NonCustodial.Admin {version}"); |
|
}); |
|
c.RoutePrefix = "";//直接根目录访问,如果是IIS发布可以注释该语句,并打开launchSettings.launchUrl |
|
c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);//折叠Api |
|
|
|
c.OAuthClientId(adminUiOptions.AdminApiConfiguration.OidcSwaggerUIClientId); |
|
c.OAuthAppName(adminUiOptions.AdminApiConfiguration.ApiName); |
|
c.OAuthUsePkce(); |
|
|
|
//c.DefaultModelsExpandDepth(-1);//不显示Models |
|
if (!adminUiOptions.SwaggerConfiguration.EnableMiniProfiler) return; |
|
// Gets or sets a Stream function for retrieving the swagger-ui page |
|
if (indexStream != null) c.IndexStream = () => indexStream; |
|
|
|
c.InjectJavascript("/swagger/mini-profiler.js?v=4.2.22+2.0"); |
|
c.InjectStylesheet("/swagger/mini-profiler.css?v=4.2.22+2.0"); |
|
}); |
|
|
|
#endregion Swagger Api文档 |
|
} |
|
|
|
/// <summary> |
|
/// Program==> SerialLog and Kestral |
|
/// </summary> |
|
/// <param name="args"></param> |
|
/// <param name="host"></param> |
|
/// <param name="webHost"></param> |
|
/// <param name="webApplicationBuilder"></param> |
|
/// <param name="adminUiOptions"></param> |
|
public static void ConfigureProgram(string[] args, IHostBuilder host, IWebHostBuilder webHost, WebApplicationBuilder webApplicationBuilder, AdminUiOptions adminUiOptions) |
|
{ |
|
try |
|
{ |
|
Log.Logger = new LoggerConfiguration().CreateBootstrapLogger(); |
|
|
|
// //configure SerialLog |
|
// host.UseSerilog((hostContext, loggerConfig) => |
|
// { |
|
// loggerConfig |
|
// .ReadFrom.Configuration(hostContext.Configuration) |
|
// .Enrich.WithProperty("ApplicationName", hostContext.HostingEnvironment.ApplicationName) |
|
//#if DEBUG |
|
// .WriteTo.Console(); |
|
//#endif |
|
// }); |
|
|
|
//配置Kestrel服务器 |
|
webHost |
|
.ConfigureAppConfiguration((hostContext, configApp) => |
|
{ |
|
var configurationRoot = configApp.Build(); |
|
configApp.AddJsonFile("configs/appsettings.json", optional: true, reloadOnChange: true); |
|
configApp.AddJsonFile("configs/serilog.json", optional: true, reloadOnChange: true); |
|
configApp.AddJsonFile("seeds/datadictionary.json", optional: true, reloadOnChange: true); |
|
configApp.AddJsonFile("seeds/identitydata.json", optional: true, reloadOnChange: true); |
|
configApp.AddJsonFile("seeds/swagger.json", optional: true, reloadOnChange: true); |
|
|
|
var env = hostContext.HostingEnvironment; |
|
configApp.AddJsonFile($"configs/appsettings.{env.EnvironmentName}.json", optional: true, |
|
reloadOnChange: true); |
|
configApp.AddJsonFile($"configs/serilog.{env.EnvironmentName}.json", optional: true, |
|
reloadOnChange: true); |
|
configApp.AddEnvironmentVariables(); |
|
configApp.AddCommandLine(args); |
|
}) |
|
//https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.features.formoptions?view=aspnetcore-6.0 |
|
.ConfigureKestrel((context, options) => |
|
{ |
|
//https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.requestformlimitsattribute?view=aspnetcore-6.0 |
|
options.Limits.MaxConcurrentConnections = 100; |
|
options.Limits.MaxConcurrentUpgradedConnections = 100; |
|
//设置应用服务器Kestrel请求体最大为100MB |
|
options.Limits.MaxRequestBodySize = int.MaxValue; |
|
}); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Log.Fatal(ex, "Host terminated unexpectedly"); |
|
} |
|
finally |
|
{ |
|
Log.CloseAndFlush(); |
|
} |
|
} |
|
} |
|
} |