yanjinhui
2025-10-20 114ffafeeb20ef7066cb2e2882bb58b96f791ab5
ÏîÄ¿´úÂë/ºó¶Ë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs
@@ -48,7 +48,7 @@
builder.Services.AddMemoryCacheSetup();//缓存
builder.Services.AddSqlsugarSetup();//SqlSugar å¯åŠ¨æœåŠ¡
if (AppSettings.GetValue("DBSeedEnable").ObjToBool())
    builder.Services.AddInitializationHostServiceSetup();//应用初始化服务注入
    builder.Services.AddInitializationHostServiceSetup();//应用初始化服务注入  åˆ›å»ºæ•°æ®åº“
builder.Services.AddHostedService<SeedDataHostedService>();
builder.Services.AddDbSetup();//Db å¯åŠ¨æœåŠ¡
@@ -111,6 +111,11 @@
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//解决服务器在HTTP响应中自动添加了一些不必要的标头
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.AddServerHeader = false;
});
var app = builder.Build();
@@ -122,7 +127,7 @@
app.UseAllServicesMiddle(builder.Services);
//FaceAI.Face.sdk_init(null);//人脸识别
app.UseSession();
//if (app.Environment.IsDevelopment())
if (app.Environment.IsDevelopment())
{
    //todo
    app.UseSwaggerAuthorized();
@@ -157,6 +162,91 @@
    //配置访问虚拟目录时文件夹别名
    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();