diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.Configure.cs b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.Configure.cs new file mode 100644 index 00000000..789cf38c --- /dev/null +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.Configure.cs @@ -0,0 +1,274 @@ +namespace Lion.AbpPro; + +public partial class AbpProHttpApiHostModule +{ + private void ConfigureHangfire(ServiceConfigurationContext context) + { + var redisStorageOptions = new RedisStorageOptions() + { + Db = context.Services.GetConfiguration().GetValue("Hangfire:Redis:DB") + }; + + Configure(options => { options.IsJobExecutionEnabled = true; }); + + context.Services.AddHangfire(config => + { + config.UseRedisStorage( + context.Services.GetConfiguration().GetValue("Hangfire:Redis:Host"), redisStorageOptions) + .WithJobExpirationTimeout(TimeSpan.FromDays(7)); + var delaysInSeconds = new[] { 10, 60, 60 * 3 }; // 重试时间间隔 + const int Attempts = 3; // 重试次数 + config.UseFilter(new AutomaticRetryAttribute() { Attempts = Attempts, DelaysInSeconds = delaysInSeconds }); + //config.UseFilter(new AutoDeleteAfterSuccessAttribute(TimeSpan.FromDays(7))); + config.UseFilter(new JobRetryLastFilter(Attempts)); + }); + } + + /// + /// 配置MiniProfiler + /// + private void ConfigureMiniProfiler(ServiceConfigurationContext context) + { + if (context.Services.GetConfiguration().GetValue("MiniProfiler:Enabled", false)) + { + context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler").AddEntityFramework(); + } + } + + /// + /// 配置JWT + /// + private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.TokenValidationParameters = + new TokenValidationParameters() + { + // 是否开启签名认证 + ValidateIssuerSigningKey = true, + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero, + ValidIssuer = configuration["Jwt:Issuer"], + ValidAudience = configuration["Jwt:Audience"], + IssuerSigningKey = + new SymmetricSecurityKey( + Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) + }; + + options.Events = new JwtBearerEvents + { + OnMessageReceived = currentContext => + { + var path = currentContext.HttpContext.Request.Path; + if (path.StartsWithSegments("/login")) + { + return Task.CompletedTask; + } + + var accessToken = string.Empty; + if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) + { + accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; + if (!string.IsNullOrWhiteSpace(accessToken)) + { + accessToken = accessToken.Split(" ").LastOrDefault(); + } + } + + if (accessToken.IsNullOrWhiteSpace()) + { + accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); + } + + if (accessToken.IsNullOrWhiteSpace()) + { + accessToken = currentContext.Request.Cookies[AbpProHttpApiHostConst.DefaultCookieName]; + } + + currentContext.Token = accessToken; + currentContext.Request.Headers.Remove("Authorization"); + currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); + + return Task.CompletedTask; + } + }; + }); + } + + + /// + /// Redis缓存 + /// + private void ConfigureCache(ServiceConfigurationContext context) + { + Configure( + options => { options.KeyPrefix = "AbpPro:"; }); + var configuration = context.Services.GetConfiguration(); + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + context.Services + .AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "AbpPro-Protection-Keys"); + } + + /// + /// 配置Identity + /// + private void ConfigureIdentity(ServiceConfigurationContext context) + { + context.Services.Configure(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); + } + + private void ConfigurationSignalR(ServiceConfigurationContext context) + { + context.Services + .AddSignalR() + .AddStackExchangeRedis(context.Services.GetConfiguration().GetValue("Redis:Configuration"), + options => { options.Configuration.ChannelPrefix = "Lion.AbpPro"; }); + } + + private void ConfigureSwaggerServices(ServiceConfigurationContext context) + { + context.Services.AddSwaggerGen( + options => + { + // 文件下载类型 + options.MapType(() => new OpenApiSchema() { Type = "file" }); + + options.SwaggerDoc("AbpPro", + new OpenApiInfo { Title = "AbpPro API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.EnableAnnotations(); // 启用注解 + options.DocumentFilter(); + options.SchemaFilter(); + // 加载所有xml注释,这里会导致swagger加载有点缓慢 + var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); + foreach (var xml in xmlPaths) + { + options.IncludeXmlComments(xml, true); + } + + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, + new OpenApiSecurityScheme() + { + Description = "直接在下框输入JWT生成的Token", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + BearerFormat = "JWT" + }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, Id = "Bearer" + } + }, + new List() + } + }); + + options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() + { + Type = SecuritySchemeType.ApiKey, + In = ParameterLocation.Header, + Name = "Accept-Language", + Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans", + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { Type = ReferenceType.SecurityScheme, Id = "ApiKey" } + }, + Array.Empty() + } + }); + }); + } + + + private void ConfigureCap(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var enabled = configuration.GetValue("Cap:Enabled", false); + if (enabled) + { + context.AddAbpCap(capOptions => + { + capOptions.SetCapDbConnectionString(configuration["ConnectionStrings:Default"]); + capOptions.UseEntityFramework(); + capOptions.UseRabbitMQ(option => + { + option.HostName = configuration.GetValue("Cap:RabbitMq:HostName"); + option.UserName = configuration.GetValue("Cap:RabbitMq:UserName"); + option.Password = configuration.GetValue("Cap:RabbitMq:Password"); + }); + + var hostingEnvironment = context.Services.GetHostingEnvironment(); + bool auth = !hostingEnvironment.IsDevelopment(); + capOptions.UseDashboard(options => + { + options.UseAuth = auth; + options.AuthorizationPolicy = AbpProCapPermissions.CapManagement.Cap; + }); + }); + } + else + { + context.AddAbpCap(capOptions => + { + capOptions.UseInMemoryStorage(); + capOptions.UseInMemoryMessageQueue(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var auth = !hostingEnvironment.IsDevelopment(); + capOptions.UseDashboard(options => { options.UseAuth = auth; }); + }); + } + } + + /// + /// 审计日志 + /// + private void ConfigureAuditLog(ServiceConfigurationContext context) + { + Configure + ( + options => + { + options.IsEnabled = true; + options.EntityHistorySelectors.AddAllEntities(); + options.ApplicationName = "Lion.AbpPro"; + } + ); + + Configure( + options => + { + options.IgnoredUrls.Add("/AuditLogs/page"); + options.IgnoredUrls.Add("/hangfire/stats"); + options.IgnoredUrls.Add("/hangfire/recurring/trigger"); + options.IgnoredUrls.Add("/cap"); + options.IgnoredUrls.Add("/"); + }); + } + + private void ConfigurationMultiTenancy() + { + Configure(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); + } +} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.cs b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.cs index ceb0446c..a49ca201 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.cs +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/AbpProHttpApiHostModule.cs @@ -15,7 +15,7 @@ namespace Lion.AbpPro typeof(AbpCachingStackExchangeRedisModule), typeof(AbpBackgroundJobsHangfireModule) )] - public class AbpProHttpApiHostModule : AbpModule + public partial class AbpProHttpApiHostModule : AbpModule { public override void OnPostApplicationInitialization(ApplicationInitializationContext context) { @@ -50,6 +50,7 @@ namespace Lion.AbpPro { app.UseMiniProfiler(); } + app.UseRouting(); app.UseCors(AbpProHttpApiHostConst.DefaultCorsPolicyName); app.UseAuthentication(); @@ -83,281 +84,5 @@ namespace Lion.AbpPro app.UseConsul(); } } - - - #region 私有配置 - - private void ConfigureHangfire(ServiceConfigurationContext context) - { - var redisStorageOptions = new RedisStorageOptions() - { - Db = context.Services.GetConfiguration().GetValue("Hangfire:Redis:DB") - }; - - Configure(options => { options.IsJobExecutionEnabled = true; }); - context.Services.AddHangfire(config => - { - config.UseRedisStorage(ConnectionMultiplexer.Connect(context.Services.GetConfiguration().GetValue("Hangfire:Redis:Host")), redisStorageOptions) - .WithJobExpirationTimeout(TimeSpan.FromDays(7)); - var delaysInSeconds = new[] { 10, 60, 60 * 3 }; // 重试时间间隔 - const int Attempts = 3; // 重试次数 - config.UseFilter(new AutomaticRetryAttribute() { Attempts = Attempts, DelaysInSeconds = delaysInSeconds }); - //config.UseFilter(new AutoDeleteAfterSuccessAttribute(TimeSpan.FromDays(7))); - config.UseFilter(new JobRetryLastFilter(Attempts)); - }); - } - - /// - /// 配置MiniProfiler - /// - private void ConfigureMiniProfiler(ServiceConfigurationContext context) - { - if (context.Services.GetConfiguration().GetValue("MiniProfiler:Enabled", false)) - { - context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler").AddEntityFramework(); - } - } - - /// - /// 配置JWT - /// - private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.TokenValidationParameters = - new TokenValidationParameters() - { - // 是否开启签名认证 - ValidateIssuerSigningKey = true, - ValidateIssuer = true, - ValidateAudience = true, - ValidateLifetime = true, - ClockSkew = TimeSpan.Zero, - ValidIssuer = configuration["Jwt:Issuer"], - ValidAudience = configuration["Jwt:Audience"], - IssuerSigningKey = - new SymmetricSecurityKey( - Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) - }; - - options.Events = new JwtBearerEvents - { - OnMessageReceived = currentContext => - { - var path = currentContext.HttpContext.Request.Path; - if (path.StartsWithSegments("/login")) - { - return Task.CompletedTask; - } - - var accessToken = string.Empty; - if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) - { - accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; - if (!string.IsNullOrWhiteSpace(accessToken)) - { - accessToken = accessToken.Split(" ").LastOrDefault(); - } - } - - if (accessToken.IsNullOrWhiteSpace()) - { - accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); - } - - if (accessToken.IsNullOrWhiteSpace()) - { - accessToken = currentContext.Request.Cookies[AbpProHttpApiHostConst.DefaultCookieName]; - } - - currentContext.Token = accessToken; - currentContext.Request.Headers.Remove("Authorization"); - currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); - - return Task.CompletedTask; - } - }; - }); - } - - - /// - /// Redis缓存 - /// - private void ConfigureCache(ServiceConfigurationContext context) - { - Configure( - options => { options.KeyPrefix = "AbpPro:"; }); - var configuration = context.Services.GetConfiguration(); - var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); - context.Services - .AddDataProtection() - .PersistKeysToStackExchangeRedis(redis, "AbpPro-Protection-Keys"); - } - - /// - /// 配置Identity - /// - private void ConfigureIdentity(ServiceConfigurationContext context) - { - context.Services.Configure(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); - } - - private void ConfigurationSignalR(ServiceConfigurationContext context) - { - var redisConnection = context.Services.GetConfiguration()["Redis:Configuration"]; - - if (redisConnection.IsNullOrWhiteSpace()) - { - throw new UserFriendlyException(message: "Redis连接字符串未配置."); - } - - context.Services.AddSignalR().AddStackExchangeRedis(redisConnection, options => { options.Configuration.ChannelPrefix = "Lion.AbpPro"; }); - } - - private void ConfigureSwaggerServices(ServiceConfigurationContext context) - { - context.Services.AddSwaggerGen( - options => - { - // 文件下载类型 - options.MapType(() => new OpenApiSchema() { Type = "file" }); - - options.SwaggerDoc("AbpPro", - new OpenApiInfo { Title = "AbpPro API", Version = "v1" }); - options.DocInclusionPredicate((docName, description) => true); - options.EnableAnnotations(); // 启用注解 - options.DocumentFilter(); - options.SchemaFilter(); - // 加载所有xml注释,这里会导致swagger加载有点缓慢 - var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); - foreach (var xml in xmlPaths) - { - options.IncludeXmlComments(xml, true); - } - - options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, - new OpenApiSecurityScheme() - { - Description = "直接在下框输入JWT生成的Token", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.Http, - Scheme = JwtBearerDefaults.AuthenticationScheme, - BearerFormat = "JWT" - }); - options.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, Id = "Bearer" - } - }, - new List() - } - }); - - options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() - { - Type = SecuritySchemeType.ApiKey, - In = ParameterLocation.Header, - Name = "Accept-Language", - Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans", - }); - - options.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { Type = ReferenceType.SecurityScheme, Id = "ApiKey" } - }, - Array.Empty() - } - }); - }); - } - - - private void ConfigureCap(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - var enabled = configuration.GetValue("Cap:Enabled", false); - if (enabled) - { - context.AddAbpCap(capOptions => - { - capOptions.SetCapDbConnectionString(configuration["ConnectionStrings:Default"]); - capOptions.UseEntityFramework(); - capOptions.UseRabbitMQ(option => - { - option.HostName = configuration.GetValue("Cap:RabbitMq:HostName"); - option.UserName = configuration.GetValue("Cap:RabbitMq:UserName"); - option.Password = configuration.GetValue("Cap:RabbitMq:Password"); - }); - - var hostingEnvironment = context.Services.GetHostingEnvironment(); - bool auth = !hostingEnvironment.IsDevelopment(); - capOptions.UseDashboard(options => - { - options.UseAuth = auth; - options.AuthorizationPolicy = AbpProCapPermissions.CapManagement.Cap; - }); - }); - } - else - { - context.AddAbpCap(capOptions => - { - capOptions.UseInMemoryStorage(); - capOptions.UseInMemoryMessageQueue(); - var hostingEnvironment = context.Services.GetHostingEnvironment(); - var auth = !hostingEnvironment.IsDevelopment(); - capOptions.UseDashboard(options => { options.UseAuth = auth; }); - }); - } - } - - /// - /// 审计日志 - /// - private void ConfigureAuditLog(ServiceConfigurationContext context) - { - Configure - ( - options => - { - options.IsEnabled = true; - options.EntityHistorySelectors.AddAllEntities(); - options.ApplicationName = "Lion.AbpPro"; - } - ); - - Configure( - options => - { - options.IgnoredUrls.Add("/AuditLogs/page"); - options.IgnoredUrls.Add("/hangfire/stats"); - options.IgnoredUrls.Add("/hangfire/recurring/trigger"); - options.IgnoredUrls.Add("/cap"); - options.IgnoredUrls.Add("/"); - }); - } - - private void ConfigurationMultiTenancy() - { - Configure(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); - } - #endregion } } \ No newline at end of file