using WIDESEAWCS_Core.Helper;
|
using WIDESEAWCS_Core.Extensions;
|
using WIDESEAWCS_Core.Middlewares;
|
using System.Reflection;
|
using WIDESEAWCS_Core.Filter;
|
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json;
|
using System.Text;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
using WIDESEAWCS_Core;
|
using WIDESEAWCS_Core.BaseServices;
|
using Autofac.Extensions.DependencyInjection;
|
using Autofac;
|
using WIDESEAWCS_WCSServer.Filter;
|
using WIDESEAWCS_Core.Authorization;
|
using WIDESEAWCS_Core.Core;
|
using WIDESEAWCS_QuartzJob.Seed;
|
using Autofac.Core;
|
using WIDESEAWCS_QuartzJob.QuartzExtensions;
|
using Microsoft.AspNetCore.Builder;
|
using WIDESEAWCS_Server.HostedService;
|
using WIDESEAWCS_Server.Filter;
|
using WIDESEAWCS_Tasks.OHT;
|
using Baidu.Aip.Face;
|
using Microsoft.Extensions.FileProviders;
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer<ContainerBuilder>(builder =>
|
{
|
builder.RegisterModule(new AutofacModuleRegister());//´øÓнӿڲãµÄ·þÎñ×¢Èë
|
builder.RegisterModule(new QuartzJobAutofacModuleRegister());
|
builder.RegisterModule<AutofacPropertityModuleReg>();//
|
}).ConfigureAppConfiguration((hostingContext, config) =>
|
{
|
hostingContext.Configuration.ConfigureApplication();
|
config.Sources.Clear();
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
|
}); ;
|
builder.ConfigureApplication();
|
|
// 2¡¢ÅäÖ÷þÎñ
|
builder.Services.AddSingleton(new AppSettings(builder.Configuration));//×¢²á
|
builder.Services.AddAllOptionRegister();//¶ÁÈ¡ÅäÖÃÎļþ
|
builder.Services.AddMemoryCacheSetup();//»º´æ
|
builder.Services.AddSqlsugarSetup();//SqlSugar Æô¶¯·þÎñ
|
if (AppSettings.GetValue("DBSeedEnable").ObjToBool())
|
builder.Services.AddInitializationHostServiceSetup();//Ó¦Óóõʼ»¯·þÎñ×¢Èë ´´½¨Êý¾Ý¿â
|
builder.Services.AddHostedService<SeedDataHostedService>();
|
builder.Services.AddDbSetup();//Db Æô¶¯·þÎñ
|
|
builder.Services.AddScoped<QuartzJobCreateDataTabel>();
|
if (AppSettings.GetValue("DBSeedEnable").ObjToBool())
|
builder.Services.AddHostedService<QuartzJobDataTableHostedService>();
|
|
builder.Services.AddWebSocketSetup();
|
|
builder.Services.AddHostedService<WebSocketHostService>();
|
|
builder.Services.AddAutoMapperSetup();
|
|
builder.Services.AddCorsSetup();
|
|
builder.Services.AddMiniProfilerSetup();
|
|
builder.Services.AddSwaggerSetup();
|
|
builder.Services.AddJobSetup();//ÈÎÎñµ÷¶È Æô¶¯·þÎñ
|
|
builder.Services.AddHttpContextSetup();
|
|
if (AppSettings.Get("QuartzJobAutoStart").ObjToBool())
|
builder.Services.AddHostedService<QuartzJobHostedService>();//ÈÎÎñµ÷¶È Æô¶¯·þÎñ
|
|
builder.Services.AddMvc(options =>
|
{
|
options.Filters.Add(typeof(ApiAuthorizeFilter));
|
options.Filters.Add(typeof(ActionExecuteFilter));
|
});
|
|
builder.Services.AddAuthorizationSetup();
|
|
builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration);//IPLimitÏÞÁ÷ Æô¶¯·þÎñ
|
|
builder.Services.AddScoped<UseServiceDIAttribute>();
|
|
builder.Services.AddSession();
|
|
builder.Services.AddHttpClient();
|
|
builder.Services.AddControllers(o =>
|
{
|
o.Filters.Add(typeof(GlobalExceptionsFilter));//È«¾ÖÒì³£
|
})
|
.AddNewtonsoftJson(options =>
|
{
|
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
|
//options.SerializerSettings.ContractResolver = new DefaultContractResolver();
|
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
|
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
options.SerializerSettings.NullValueHandling = NullValueHandling.Include;
|
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
|
options.SerializerSettings.Converters.Add(new StringEnumConverter());
|
});
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|
//½â¾ö·þÎñÆ÷ÔÚHTTPÏìÓ¦ÖÐ×Ô¶¯Ìí¼ÓÁËһЩ²»±ØÒªµÄ±êÍ·
|
builder.WebHost.ConfigureKestrel(serverOptions =>
|
{
|
serverOptions.AddServerHeader = false;
|
});
|
|
var app = builder.Build();
|
|
// 3¡¢ÅäÖÃÖмä¼þ
|
app.UseMiniProfiler();//ÐÔÄÜ·ÖÎöÆ÷
|
app.ConfigureApplication();//ÅäÖÃÎļþ
|
app.UseApplicationSetup();//Æô¶¯ÅäÖÃ
|
|
app.UseAllServicesMiddle(builder.Services);
|
//FaceAI.Face.sdk_init(null);//ÈËÁ³Ê¶±ð
|
app.UseSession();
|
if (app.Environment.IsDevelopment())
|
{
|
//todo
|
app.UseSwaggerAuthorized();
|
app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("WIDESEAWCS_Server.index.html") ?? throw new Exception("δÕÒµ½WIDESEAWCS_Server.index.htmlÎļþ"));
|
}//ÅжÏÊÇ·ñÐèÒª´ò¿ªswagger
|
|
app.UseIpLimitMiddle();
|
app.UseApiLogMiddleware();
|
//todo
|
//app.UseRecordAccessLogsMiddle();
|
|
app.UseCors(AppSettings.Get(new string[] { "Cors", "PolicyName" }));
|
|
DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions();
|
defaultFilesOptions.DefaultFileNames.Clear();
|
defaultFilesOptions.DefaultFileNames.Add("index.html");
|
app.UseDefaultFiles(defaultFilesOptions);
|
app.UseMiddleware<HttpRequestMiddleware>();
|
app.UseStaticFiles();
|
var staticPath = Path.Combine(Directory.GetCurrentDirectory(), "Record");
|
if (!Directory.Exists(staticPath))
|
{
|
Directory.CreateDirectory(staticPath);
|
}
|
|
Console.WriteLine($"¾²Ì¬Îļþ·¾¶£º{staticPath}");
|
|
app.UseStaticFiles(new StaticFileOptions()
|
{
|
FileProvider = new PhysicalFileProvider(
|
Path.Combine(Directory.GetCurrentDirectory(), @"Record")),
|
//ÅäÖ÷ÃÎÊÐéÄâĿ¼ʱÎļþ¼Ð±ðÃû
|
RequestPath = "/Record"
|
});
|
|
//X-Content-Type-Options¡±Í·È±Ê§»ò²»°²È«
|
// ʹÓà AddDefaultSecurityHeaders ·½·¨Ìí¼ÓÒ»×éÍÆ¼öµÄ°²È«±êÍ·
|
app.UseSecurityHeaders(policies => policies
|
.AddFrameOptionsDeny() // Ìí¼Ó X-Frame-Options: DENY
|
.AddContentTypeOptionsNoSniff() // Õâ¾ÍÊÇÄãÐèÒªµÄ X-Content-Type-Options: nosniff
|
.AddXssProtectionBlock() // Ìí¼Ó X-XSS-Protection: 1; mode=block
|
.AddStrictTransportSecurityMaxAgeIncludeSubDomains(maxAgeInSeconds: 60 * 60 * 24 * 365) // Ìí¼Ó HSTS Í·
|
// ÒÆ³ý·þÎñÆ÷ÐÅϢͷ
|
//.AddCustomHeader("X-Powered-By", string.Empty) // ×¢ÒâÊÇ AddCustomHeader
|
//½â¾öContent-Security-Policyȱʧ
|
.AddContentSecurityPolicy(builder =>
|
{
|
builder.AddDefaultSrc().Self();
|
builder.AddScriptSrc().Self();
|
builder.AddStyleSrc().Self();
|
builder.AddImgSrc().Self().Data();
|
builder.AddFontSrc().Self();
|
})
|
|
);
|
// ÊÖ¶¯ÒƳý¶àÓàÏìӦͷ£¨¾É°æ°ü±ØÐ룩
|
app.Use(async (context, next) =>
|
{
|
context.Response.Headers.Remove("Server");
|
context.Response.Headers.Remove("X-Powered-By");
|
context.Response.Headers.Remove("x-miniprofiler-ids");//miniprofilerµÄÖ¸±êÍ·
|
await next();
|
});
|
|
// À¹½ØÃô¸Ð·¾¶£¬·µ»Ø 404
|
app.Use(async (context, next) =>
|
{
|
var path = context.Request.Path.Value ?? string.Empty;
|
|
var blacklist = new[]
|
{
|
"/.git", "/.svn", "/.env", "/backup", "/backups", "/config", "/database", "/.idea", "/.vscode", "/node_modules"
|
};
|
|
if (path.Contains("..") || blacklist.Any(b => path.StartsWith(b, StringComparison.OrdinalIgnoreCase)))
|
{
|
context.Response.StatusCode = StatusCodes.Status404NotFound;
|
await context.Response.WriteAsync("Not Found");
|
return;
|
}
|
|
await next();
|
});
|
|
//Ó¦ÓóÌÐòÖ¸±êÊý¾Ý±©Â¶
|
app.Use(async (context, next) =>
|
{
|
var path = context.Request.Path.Value ?? string.Empty;
|
// ÐèÒª±£»¤µÄ¶Ëµãǰ׺
|
var sensitivePrefixes = new[]
|
{
|
"/metrics", "/health", "/actuator", "/diagnostics", "/debug", "/metrics/prometheus"
|
};
|
|
if (sensitivePrefixes.Any(p => path.StartsWith(p, StringComparison.OrdinalIgnoreCase)))
|
{
|
var secret = app.Configuration["Internal:MetricsKey"]; // ÔÚ appsettings.json »ò »·¾³±äÁ¿ÀïÅäÖÃ
|
if (string.IsNullOrWhiteSpace(secret))
|
{
|
// δÅäÖÃÃÜÔ¿£ºÎªÁ˰²È«¾Ü¾ø·ÃÎÊ
|
context.Response.StatusCode = StatusCodes.Status403Forbidden;
|
await context.Response.WriteAsync("Forbidden");
|
return;
|
}
|
|
if (!context.Request.Headers.TryGetValue("X-Internal-Secret", out var provided) || provided != secret)
|
{
|
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
await context.Response.WriteAsync("Unauthorized");
|
return;
|
}
|
}
|
|
await next();
|
});
|
app.UseHttpsRedirection();
|
|
|
|
app.UseCookiePolicy();
|
app.UseStatusCodePages();
|
|
app.UseRouting();
|
|
app.UseAuthentication();
|
app.UseAuthorization();
|
|
app.MapControllers();
|
|
app.Run();
|