using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.WebEncoders; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using NLog; using NLog.Web; using System.Runtime.InteropServices; using System.Text; using System.Text.Encodings.Web; using System.Text.Unicode; using YieldChain.Commons; using YLErp.Abstract; using YLErp.Serialization; using YLErp.Services.CashRecordModule; using YLErp.Web.App; using YLErp.Web.App.KafkaTask; using YLErp.Web.Hubs; using YLErp.Web.Middleware; using LogLevel = Microsoft.Extensions.Logging.LogLevel; JsonConvert.DefaultSettings = JsonHelper.GetDefaultSettings; var logger = LogManager.Setup().GetCurrentClassLogger(); logger.Debug("init main"); try { var builder = WebApplication.CreateBuilder(args); var configuration = builder.Configuration; // Add services to the container. builder.Services.AddHttpClient(); builder.Services.AddControllersWithViews().AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = null; options.JsonSerializerOptions.Converters.Add(new AntiXssConverter()); options.JsonSerializerOptions.Converters.Add(CustomDoubleConvert.Default); options.JsonSerializerOptions.Converters.Add(new CustomDateTimeConverter()); }).AddRazorRuntimeCompilation(); //视图渲染绑定中文乱码问题 builder.Services.Configure(options => options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All)); builder.Services.Configure(options => { options.ValueCountLimit = 1000000; options.ValueLengthLimit = 1024 * 1024 * 100; // 100MB max len form data options.MultipartBodyLengthLimit = int.MaxValue; //不限制文件上传大小 }); builder.Services.Configure(options => options.MaxModelBindingCollectionSize = 1000000); builder.Services.Configure(builder.Configuration.GetSection("KafkaConfig")); builder.Services.Configure(builder.Configuration.GetSection("ExternalCashFlow")); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddTransient(); builder.Services.AddResponseCompression(options => { options.Providers.Add(); options.Providers.Add(); options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "image/svg+xml" }); }); builder.Services.AddAuthentication(AuthHelper.CookieAuthType) .AddCookie(AuthHelper.CookieAuthType, options => { options.LoginPath = "/Account/Login/"; options.AccessDeniedPath = "/Account/Login/"; options.ExpireTimeSpan = TimeSpan.FromSeconds(AuthHelper.ExpireInSeconds); options.SlidingExpiration = true; options.Events = new CookieAuthenticationEvents { OnRedirectToLogin = context => { var accept = context.Request.Headers["Accept"].ToString(); var xrw = context.Request.Headers["X-Requested-With"].ToString(); var isAjax = xrw == "XMLHttpRequest" || !accept.Contains("text/html"); logger.Info($"[CookieAuth] OnRedirectToLogin Path={context.Request.Path} Accept={accept} X-Requested-With={xrw} IsAjax={isAjax}"); if (isAjax) { context.Response.StatusCode = 401; return Task.CompletedTask; } context.Response.Redirect(context.RedirectUri); return Task.CompletedTask; }, OnRedirectToAccessDenied = context => { var accept = context.Request.Headers["Accept"].ToString(); var xrw = context.Request.Headers["X-Requested-With"].ToString(); var isAjax = xrw == "XMLHttpRequest" || !accept.Contains("text/html"); logger.Info($"[CookieAuth] OnRedirectToAccessDenied Path={context.Request.Path} Accept={accept} X-Requested-With={xrw} IsAjax={isAjax}"); if (isAjax) { context.Response.StatusCode = 403; return Task.CompletedTask; } context.Response.Redirect(context.RedirectUri); return Task.CompletedTask; } }; }) .AddJwtBearer(AuthHelper.JwtAuthType, options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateLifetime = true, //是否验证失效时间 ClockSkew = TimeSpan.FromSeconds(AuthHelper.ExpireInSeconds), ValidateAudience = false, ValidateIssuer = false, //是否验证Issuer ValidateIssuerSigningKey = true, //是否验证SecurityKey IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AuthHelper.JwtSecretKey)) }; }); builder.Services.AddAuthorization(options => { options.AddPolicy(AuthHelper.CookieAuthType, policy => policy.RequireAssertion(context => ErpAuthorizeHandler.Default.Handle(context))); options.AddPolicy(AuthHelper.JwtAuthType, policy => policy.RequireAssertion(context => ErpAuthorizeHandler.Default.Handle(context))); }); //NLog: Setup NLog for Dependency injection builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(LogLevel.Trace); builder.Host.UseNLog(); // Save IServerCollection YLServiceLocator.SetServiceCollection(builder.Services); Server.Initialize(builder.Environment, builder.Configuration); Startup.Start(builder.Configuration); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddCaptcha(builder.Configuration, option => { option.ImageOption.Width = 256; // 验证码宽度 option.ImageOption.Height = 34; // 验证码高度 option.ExpirySeconds = 60; // 验证码过期时间 option.IgnoreCase = true; // 比较时是否忽略大小写 option.ImageOption.BubbleCount = 0; option.ImageOption.InterferenceLineCount = 3; // 干扰线数量 }); builder.Services.AddSignalR(); //============================================ var app = builder.Build(); // Save IServerProvider YLServiceLocator.SetServiceProvider(app.Services); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { } app.UseMiddleware(); // 计息计算过程追踪(?swaptrace=1 / X-SwapCalc-Trace:1 开启,详见 SwapCalcTraceMiddleware) app.UseMiddleware(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // Linux 路径区分大小写,需要对静态文件做处理 app.UseMiddleware(); } app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); // Token续期中间件 app.UseMiddleware(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapHub("/swapflow/combookinghub"); // 映射Hub路径 endpoints.MapHub("/swapflow/resethub"); // 映射Hub路径 endpoints.MapHub("/tradeconfirm/sendemailhub"); // 映射Hub路径 endpoints.MapHub("/tradeconfirm/sendoahub"); // 映射OA Hub路径 }); var provider = new FileExtensionContentTypeProvider(); provider.Mappings[".pdf"] = "application/pdf"; provider.Mappings[".doc"] = "application/msword"; provider.Mappings[".docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; provider.Mappings[".xls"] = "application/vnd.ms-excel"; provider.Mappings[".xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Server.MapPath("App_Docs")), RequestPath = "/App_Docs", ContentTypeProvider = provider }); app.UseResponseCompression(); app.MapAreaControllerRoute( name: "MyAreaAdmin", areaName: "Admin", pattern: "Admin/{controller=Home}/{action=Index}/{id?}"); app.MapControllerRoute( name: "mapi", pattern: "m/api/{*path}"); app.MapControllerRoute( name: "v3", pattern: "v3/{*path}", new { controller = "V3", action = "Index" }); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); } catch (Exception ex) { // NLog: catch setup errors logger.Error(ex, "Stopped program because of exception"); throw; } finally { // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) LogManager.Shutdown(); }