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
|
|||
|
|
|||
|
}
|