299 lines
9.8 KiB
C#
299 lines
9.8 KiB
C#
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
|
||
|
||
} |