网站首页 网站源码

using System.Threading.RateLimiting;
using Dpz.Core.Infrastructure.RateLimiting;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Primitives;
using StackExchange.Redis;
const string corsScheme = "Open-Dpz-Core";
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext().CreateBootstrapLogger();
try
{
    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseAgileConfig(new ConfigClient(builder.Configuration));
    var configuration = builder.Configuration;
    CdnBaseAddress =
        configuration["CDNBaseAddress"]
        ?? throw new Exception("configuration node CDNBaseAddress is null or empty");
    var logSeq = configuration.GetSection("LogSeq").Get<LogSeq>();
    builder.Host.ConfigurationLog(logSeq);
    const int threads = 100;
    if (ThreadPool.SetMinThreads(threads, threads))
    {
        Log.Information(
            "set worker threads:{WorkerThreads},set completion  port threads {CompletionPortThreads}",
            threads,
            threads
        );
    }
    builder
        .WebHost.UseKestrel(
            (_, option) =>
            {
                option.AddServerHeader = false;
                option.ConfigureHttpsDefaults(x =>
                    x.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
                );
            }
        )
        .UseIIS()
        .UseIISIntegration();
    #region services
    var services = builder.Services;
    services.AddMvc(x =>
    {
        x.Filters.Add(typeof(GlobalFilter));
        x.Filters.Add(new TypeFilterAttribute(typeof(ExceptionHandleAttribute)));
    });
    //压缩
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            ["application/font-woff2", "image/svg+xml", "text/plain", "application/lrc"]
        );
        options.EnableForHttps = true;
    });
    services.Configure<BrotliCompressionProviderOptions>(options =>
    {
        options.Level = CompressionLevel.Optimal;
    });
    services.Configure<GzipCompressionProviderOptions>(options =>
    {
        options.Level = CompressionLevel.Optimal;
    });
#if DEBUG
    services.Configure<KestrelServerOptions>(options =>
    {
        options.Limits.MaxRequestBodySize = int.MaxValue;
    });
#endif
    services.AddRateLimiter(options =>
    {
        options.AddFixedWindowLimiter(
            "comment",
            opt =>
            {
                opt.AutoReplenishment = true;
                opt.PermitLimit = 3;
                opt.Window = TimeSpan.FromMinutes(1);
                opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
                opt.QueueLimit = 2;
            }
        );
    });
    //依赖注入
    services.AddDefaultServices(configuration).AddInject();
    //缩小html
    services
        .AddWebMarkupMin(x =>
        {
            x.AllowMinificationInDevelopmentEnvironment = true;
            x.AllowCompressionInDevelopmentEnvironment = true;
        })
        .AddHtmlMinification(x =>
        {
            var settings = x.MinificationSettings;
            settings.RemoveOptionalEndTags = false;
        })
        .AddXmlMinification()
        .AddHttpCompression(option =>
        {
            option.CompressorFactories = new List<ICompressorFactory>
            {
                new BuiltInBrotliCompressorFactory(
                    new BuiltInBrotliCompressionSettings { Level = CompressionLevel.Optimal }
                ),
                new DeflateCompressorFactory(
                    new DeflateCompressionSettings { Level = CompressionLevel.Optimal }
                ),
                new GZipCompressorFactory(
                    new GZipCompressionSettings { Level = CompressionLevel.Optimal }
                ),
            };
        });
    // 响应式服务
    services.AddResponsive();
    // 设备识别
    services.AddDetection();
    // .AddDevice().AddBrowser()
    // .AddPlatform()
    // .AddEngine()
    // .AddCrawler();
    //注册 响应服务
    services.AddResponsive();
    //services.AddHostedService<TimedHostedService>();
    services.AddControllersWithViews();
    //注册 缓存中间件
    services.AddResponseCaching();
    var redisConnectionString =
        configuration.GetConnectionString("redis")
        ?? throw new Exception("configuration node redis is null or empty");
    //缓存
    services.AddRedisCacheOutput(redisConnectionString);
    services.AddBusinessServices(configuration);
    // 注册限流服务
    services.AddIpRateLimit();
    // Cors
    services.AddCors(options =>
    {
        options.AddPolicy(
            corsScheme,
            cfg =>
            {
                cfg.WithOrigins(configuration.GetSection("Origins").Get<string[]>() ?? [])
                    .WithMethods("GET", "PUT", "POST", "DELETE", "PATCH", "OPTION")
                    .AllowAnyHeader();
            }
        );
    });
    //注册 身份认证服务
    services.Configure<TokenManagement>(configuration.GetSection("TokenManagement"));
    services
        .AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = AuthorizeCookieName;
            x.DefaultChallengeScheme = AuthorizeCookieName;
            x.DefaultSignInScheme = AuthorizeCookieName;
        })
        .AddCookie(
            AuthorizeCookieName,
            options =>
            {
                options.LoginPath = "/login.html";
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            }
        )
        .AddJwtBearer(
            JwtBearerDefaults.AuthenticationScheme,
            x =>
            {
                var token = configuration.GetSection("TokenManagement").Get<TokenManagement>();
                if (token == null)
                {
                    return;
                }
                x.RequireHttpsMetadata = true;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(token.Secret)
                    ),
                    ValidIssuer = token.Issuer,
                    ValidAudience = token.Audience,
                    ValidateIssuer = true,
                    ValidateAudience = true,
                };
            }
        );
    //services.AddAuthorization(x => )
    services
        .AddIdentityCore<VmUserInfo>(x =>
            x.ClaimsIdentity.SecurityStampClaimType = AuthorizeCookieName
        )
        .AddUserStore<UserStore>()
        .AddSignInManager<ApplicationSignInManager>();
    services.AddDataProtection().SetApplicationName(AuthorizeCookieName);
    services
        .AddOptions<KeyManagementOptions>()
        .Configure<IServiceScopeFactory>(
            (options, factory) =>
            {
                options.XmlRepository = new XmlRepositoryService(
                    factory,
                    AuthorizeCookieName + ".Key"
                );
            }
        );
    //register SignalR
    services
        .AddSignalR(x =>
        {
            x.HandshakeTimeout = TimeSpan.FromMinutes(2);
            x.MaximumReceiveMessageSize = 32768;
        })
        .AddStackExchangeRedis(
            redisConnectionString,
            options =>
            {
                options.Configuration.ChannelPrefix = RedisChannel.Literal("Dpz.Core.signalR");
            }
        );
    // 添加Hangfire 服务
    services.HangfireService(configuration);
    #endregion
    var app = builder.Build();
    #region configuration
    if (app.Environment.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseRouteDebugger();
    }
    var supportedCultures = new[] { new CultureInfo("zh-CN") };
    app.UseRequestLocalization(
        new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("zh-CN"),
            // Formatting numbers, dates, etc.
            SupportedCultures = supportedCultures,
            // UI strings that we have localized.
            SupportedUICultures = supportedCultures,
        }
    );
    app.UseSerilogRequestLogging(options =>
    {
        options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
        {
            diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
            diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
            diagnosticContext.Set("UserAgent", httpContext.Request.Headers.UserAgent.ToString());
            diagnosticContext.Set("IpAddress", httpContext.Request.GetIpAddress());
            var referer = httpContext.Request.Headers.Referer;
            if (!StringValues.IsNullOrEmpty(referer))
            {
                diagnosticContext.Set("Referer", referer);
            }
        };
    });
    
    //启用压缩
    app.UseResponseCompression();
    // 添加IP限流中间件
    app.UseIpRateLimit();
    
    // 拒绝爬虫
    app.UseRejectBots();
    // app.UseHsts();
    // app.UseHttpsRedirection();
    //启用静态文件
    app.UseStaticFiles(
        new StaticFileOptions()
        {
            OnPrepareResponse = ctx =>
            {
                // 如果访问静态资源的图片,那么设置缓存
                if (
                    ctx.Context.Response.ContentType?.StartsWith(
                        "image/",
                        StringComparison.CurrentCultureIgnoreCase
                    ) == true
                )
                {
                    ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000");
                    ctx.Context.Response.Headers.Append(
                        "Expires",
                        DateTime.UtcNow.AddDays(30).ToString("R", CultureInfo.InvariantCulture)
                    );
                }
            },
        }
    );
    app.UseWebMarkupMin();
    //启用缓存中间件
    app.UseResponseCaching();
    //启用响应服务
    app.UseResponsive();
    app.UseCors(corsScheme);
    app.UseDetection();
    app.UseRouting().UseMiddleware<HttpResponseHeaderHandel>().UseRecordRequest();
    //启用身份认证
    app.UseAuthentication();
    //启用身份授权
    app.UseAuthorization();
    // 路由
    app.ConfigurationRoute();
    //系统初始化
    app.Init();
    // 使用 hangfire UI,及周期性任务调度
    app.HangfireSetting();
    app.MapGet(
        "/ping",
        requestDelegate: async context =>
        {
            await context.Response.WriteAsJsonAsync(context.Request.Headers);
        }
    );
    #endregion
    Log.Information("Starting web core host");
    app.Run();
}
catch (Exception ex)
{
    Console.Error.WriteLine(ex);
    Log.Fatal(ex, "Host terminated unexpectedly");
}
public partial class Program
{
    /// <summary>
    /// 身份认证Cookie名称
    /// </summary>
    public const string AuthorizeCookieName = "Dpz.Web.Core.Authoriza";
    /// <summary>
    /// 获取CDN基础地址
    /// </summary>
    public static string CdnBaseAddress { get; private set; } = "";
    /// <summary>
    /// 版本号
    /// </summary>
    public static string Version =>
        Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "_version";
}
这段代码是一个 ASP.NET Core 应用程序的启动代码,主要用于配置和初始化 Web 应用程序的各个方面。以下是对代码功能的详细解释:
Serilog 进行日志记录,创建一个引导日志记录器。WebApplication.CreateBuilder(args) 创建一个应用程序构建器。WebMarkupMin 进行 HTML 和 XML 的最小化。这段代码是一个复杂的 ASP.NET Core 应用程序的启动配置,涵盖了从日志记录、服务注册、身份认证、CORS、SignalR、Hangfire 到中间件配置等多个方面,旨在构建一个高效、可扩展的 Web 应用程序。
