TemplatePro/BZPT.Api/Program.cs

299 lines
9.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}