TemplatePro/BZPT.Api/Program.cs

299 lines
9.8 KiB
C#
Raw Normal View History

2025-03-02 23:30:03 +08:00
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using NPlatform.Infrastructure.Config;
using NPlatform.Middleware;
using NPlatform.API;
using NPlatform.DI;
using NPlatform.Repositories;
using BZPT.IdentityServer;
using Consul;
using MediatR;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using SqlSugar;
using IGeekFan.AspNetCore.Knife4jUI;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Cryptography.X509Certificates;
using BZPT.Repositories;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NPlatform.Infrastructure.Config.Section;
using ServiceStack;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
// 创建 Web 应用构建器
var builder = WebApplication.CreateBuilder(args);
var serviceConfig = builder.Configuration.GetServiceConfig();
// 配置日志
var log = builder.Logging.AddLog4Net();
log.AddConsole();
log.AddDebug(); // 添加调试日志
log.SetMinimumLevel(LogLevel.Debug); // 设置最低日志级别为 Debug
// 注册服务
RegisterServices(builder);
// 构建应用
var app = builder.Build();
// 配置应用中间件
ConfigureApp(app);
// 运行应用
app.Run();
// 注册服务方法
void RegisterServices(WebApplicationBuilder builder)
{
//// 替换控制器激活器,支持属性注入
builder.Services.Replace(ServiceDescriptor.Scoped<IControllerActivator, ServiceBasedControllerActivator>());
//builder.Services.AddSameSiteCookiePolicy();
string serviceName = serviceConfig.ServiceName;
// 添加健康检查
builder.Services.AddHealthChecks().AddCheck<NHealthChecks>(serviceName);
// 添加内存缓存
builder.Services.AddMemoryCache(t => { t.SizeLimit = 1048576 * 500; });
// 集成 Autofac
builder.Services.AddAutofac();
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// 配置主机
builder.Host.Configure(builder.Configuration, new RepositoryOptions());
// 配置数据库上下文
ConfigureDatabaseContext(builder);
// 配置控制器和 JSON 序列化
builder.Services.AddControllers(mvcOptions =>
{
mvcOptions.Filters.Remove(mvcOptions.Filters.OfType<UnsupportedContentTypeFilter>().FirstOrDefault());
}).AddJsonOptions(options =>
{
// 空字段不响应
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
// 时间格式化响应
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter("yyyy-MM-dd HH:mm:ss"));
});
// 配置 API 行为选项
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = actionContext =>
{
var errors = actionContext.ModelState?.Where(e => e.Value.Errors.Count > 0);
StringBuilder strError = new StringBuilder();
foreach (var error in errors)
{
var msg = error.Value.Errors.FirstOrDefault()?.ErrorMessage;
if (!string.IsNullOrWhiteSpace(msg))
strError.Append(msg);
}
return new FailResult<object>("未处理异常:"+strError.ToString());
};
});
// 配置 CORS
ConfigureCors(builder);
// 配置 Swagger
ConfigureSwagger(builder, serviceConfig);
// 添加身份验证和授权服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
// IdentityServer 的地址
options.Authority = builder.Configuration["AuthorityServer"];
// 允许 HTTPS 不安全连接(仅用于开发环境)
options.RequireHttpsMetadata = false;
// API 的名称,应与 IdentityServer 中配置的 API 资源名称一致
options.ApiName =serviceConfig.ServiceID;
});
// 添加授权策略
builder.Services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
});
// 全局启用授权
builder.Services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
// 添加 MVC
builder.Services.AddMvc();
}
// 配置数据库上下文方法
void ConfigureDatabaseContext(WebApplicationBuilder builder)
{
var dbHost = builder.Configuration["DB_HOST"];
var dbPort = builder.Configuration["DB_PORT"];
var dbName = builder.Configuration["DB_NAME"];
var dbUser = builder.Configuration["DB_USER"];
var dbPass = builder.Configuration["DB_PASSWORD"];
builder.Services.AddSingleton<DBContext>(serviceProvider =>
{
var logger = serviceProvider.GetRequiredService<ILogger<DBContext>>();
return new DBContext($"Server={dbHost};Port={dbPort};DATABASE={dbName};User Id={dbUser};PWD={dbPass};", DbType.Dm, logger, ConfigId: "default");
});
}
// 配置 Swagger 方法
void ConfigureSwagger(WebApplicationBuilder builder, IServiceConfig serviceConfig)
{
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc($"{serviceConfig.ServiceName}", new OpenApiInfo { Title = serviceConfig.ServiceName+" 接口文档。", Version = serviceConfig.ServiceVersion });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT 授权,标头使用 Bearer 方案。示例: \"Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{serviceConfig.ServiceName}.xml"), true);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new List<string>()
}
});
c.AddServer(new OpenApiServer()
{
Url = "",
Description = "vvv"
});
c.CustomOperationIds(apiDesc =>
{
var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
if (controllerAction != null)
return controllerAction.ControllerName + "-" + controllerAction.ActionName;
else return "";
});
});
}
// 配置 CORS方法
async void ConfigureCors(WebApplicationBuilder builder)
{
var serviceProvider = builder.Services.BuildServiceProvider();
var dBContext = serviceProvider.GetRequiredService<DBContext>();
var allowedOrigins = builder.Configuration["AllowedOrigins"];
var originsArray = string.IsNullOrEmpty(allowedOrigins)
? new List<string>()
: new List<string>(allowedOrigins.Split(',', StringSplitOptions.RemoveEmptyEntries));
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsMy", policy =>
{
policy.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins(originsArray.ToArray()) // 明确指定允许的源
.AllowCredentials().SetIsOriginAllowed(_ => true); // 允许凭证(如 cookies
});
});
}
// 配置应用中间件方法
void ConfigureApp(WebApplication app)
{
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Fail");
app.UseHsts();
}
if (!app.Environment.IsProduction())
{
app.UseSwagger();
var serviceConfig = app.Configuration.GetServiceConfig();
app.UseKnife4UI(c =>
{
c.RoutePrefix = "swagger";
c.SwaggerEndpoint($"/{serviceConfig.ServiceName}/swagger.json", serviceConfig.ServiceName);
});
}
app.UseHealthChecks("/healthChecks");
var defaultFilesOptions = new DefaultFilesOptions();
defaultFilesOptions.DefaultFileNames.Clear();
defaultFilesOptions.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(defaultFilesOptions);
app.UseStaticFiles();
app.UseAntiforgery();
app.UseRouting();
app.UseCors("CorsMy");
app.UseAuthentication();
app.UseAuthorization();// 显式处理所有 OPTIONS 请求
app.MapMethods("/{**path}", new[] { "OPTIONS" }, () => Results.NoContent())
.RequireCors("CorsMy");
app.MapControllers();
app.Use(async (context, next) =>
{
var requestPath = context.Request.Path.Value;
#if DEBUG
Console.WriteLine(requestPath);
await next(context);
return;
#endif
if (DateTime.Now.Hour >= 23 || DateTime.Now.Hour < 7)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("系统维护中~");
}
else
{
await next(context);
}
});
app.MapControllers(); // 强制对控制器应用 CORS
}