using Autofac; using Autofac.Extensions.DependencyInjection; using EntrustSettle; using EntrustSettle.Common; using EntrustSettle.Common.Core; using EntrustSettle.Common.Helper; using EntrustSettle.Extensions; using EntrustSettle.Extensions.Middlewares; using EntrustSettle.Extensions.ServiceExtensions; using EntrustSettle.Filter; using EntrustSettle.Hubs; using EntrustSettle.Serilog.Utility; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.IdentityModel.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using Serilog; using System.IdentityModel.Tokens.Jwt; using System.Reflection; using System.Text; internal class Program { private static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // 1、配置host与容器 builder.Host .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureContainer(builder => { builder.RegisterModule(new AutofacModuleRegister()); builder.RegisterModule(); }) .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(); Permissions.IsUseIds4 = AppSettings.app(["Startup", "IdentityServer4", "Enabled"]).ObjToBool(); RoutePrefix.Name = AppSettings.app(["AppSettings", "RoutePrefix"]).ObjToString(); /* 清除默认的声明映射关系,使得JWT中的声明名称原封不动地传递到应用程序中,而不进行任何转换。这样,你就可以按照自己的需求来处理JWT中的声明了。*/ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); builder.Services.AddCacheSetup(); builder.Services.AddSqlsugarSetup(); builder.Services.AddDbSetup(); builder.Services.AddInitializationHostServiceSetup(); builder.Host.AddSerilogSetup(); builder.Services.AddMapsterSetup(); builder.Services.AddCorsSetup(); builder.Services.AddSwaggerSetup(); builder.Services.AddJobSetup(); builder.Services.AddHttpContextSetup(); builder.Services.AddAppTableConfigSetup(builder.Environment); builder.Services.AddHttpPollySetup(); builder.Services.AddRedisInitMqSetup(); builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration); builder.Services.AddSignalR().AddNewtonsoftJsonProtocol(); builder.Services.AddAuthorizationSetup(); if (Permissions.IsUseIds4) { // 使用 Ids4权限 认证服务 builder.Services.AddAuthentication_Ids4Setup(); } else { // 使用 JWT权限 认证服务 builder.Services.AddAuthentication_JWTSetup(); } builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration); builder.Services.Configure(x => x.AllowSynchronousIO = true) .Configure(x => x.AllowSynchronousIO = true); builder.Services.AddSession(); builder.Services.AddControllers(o => { // 全局异常过滤 o.Filters.Add(typeof(GlobalExceptionsFilter)); // 全局路由权限公约 //o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); // 全局路由前缀,统一修改路由 o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name))); }) //MVC全局配置Json序列化处理 .AddNewtonsoftJson(options => { //忽略循环引用 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //不使用驼峰样式的key options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //设置时间格式 options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; //设置本地时间而非UTC时间 options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; //添加Enum转string options.SerializerSettings.Converters.Add(new StringEnumConverter()); //将long类型转为string options.SerializerSettings.Converters.Add(new NumberConverter(NumberConverterShip.Int64)); }); builder.Services.AddRabbitMQSetup(); builder.Services.AddKafkaSetup(builder.Configuration); builder.Services.AddEventBusSetup(); // 替换控制器激活器 builder.Services.Replace(ServiceDescriptor.Transient()); //支持编码大全 例如:支持 System.Text.Encoding.GetEncoding("GB2312") System.Text.Encoding.GetEncoding("GB18030") Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // 3、配置中间件 var app = builder.Build(); IdentityModelEventSource.ShowPII = true; // 显示身份验证错误详细信息 // 大简云的ids4返回的token里只有用户id,没有Name、公司名称等信息,所以这里手动赋值一下 app.UseSetAppUserMiddleware(); app.ConfigureApplication(); app.UseApplicationSetup(); app.UseResponseBodyRead(); if (app.Environment.IsDevelopment()) { // 在开发环境中,使用异常页面,这样可以暴露错误堆栈信息,所以不要放在生产环境。 app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // 在非开发环境中,使用HTTP严格安全传输(or HSTS) 对于保护web安全是非常重要的。 // 强制实施 HTTPS 在 ASP.NET Core,配合 app.UseHttpsRedirection //app.UseHsts(); } app.UseEncryptionRequest(); app.UseEncryptionResponse(); app.UseExceptionHandlerMiddle(); // 异常处理 app.UseIpLimitMiddle(); // ip限流 app.UseRequestResponseLogMiddle(); // 请求响应日志 app.UseRecordAccessLogsMiddle(); // 记录访问日志 app.UseSignalRSendMiddle(); // SignalR发送消息 app.UseIpLogMiddle(); // IP记录 app.UseAllServicesMiddle(builder.Services); // 查看所有注入的服务 app.UseSession(); // Swagger // app.UseSwaggerAuthorized(); app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("EntrustSettle.Api.swagger_index.html")); // ↓↓↓↓↓↓ 注意下边这些中间件的顺序,很重要 ↓↓↓↓↓↓ // CORS跨域 app.UseCors(AppSettings.app(new string[] { "Startup", "Cors", "PolicyName" })); // 跳转https //app.UseHttpsRedirection(); // 使用静态文件 DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); defaultFilesOptions.DefaultFileNames.Clear(); defaultFilesOptions.DefaultFileNames.Add("swagger_index.html"); app.UseDefaultFiles(defaultFilesOptions); app.UseStaticFiles(); app.UseCookiePolicy(); // 返回错误码 app.UseStatusCodePages(); // Serilog请求日志 app.UseSerilogRequestLogging(options => { options.MessageTemplate = SerilogRequestUtility.HttpMessageTemplate; options.GetLevel = SerilogRequestUtility.GetRequestLevel; options.EnrichDiagnosticContext = SerilogRequestUtility.EnrichFromRequest; }); app.UseRouting(); // 这种自定义授权中间件,可以尝试,但不推荐 // app.UseJwtTokenAuth(); // 测试用户,用来通过鉴权 if (builder.Configuration.GetValue("AppSettings:UseLoadTest")) { app.UseMiddleware(); } app.UseAuthentication(); // 认证中间件 app.UseAuthorization(); // 授权中间件 app.MapControllers(); app.MapHub("/api2/chatHub"); // 4、运行 app.Run(); } }