Abp Vnext 的 Vue3 实现版本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

371 lines
15 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CompanyName.ProjectName.ConfigurationOptions;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CompanyName.ProjectName.EntityFrameworkCore;
using CompanyNameProjectName.Extensions.Filters;
using Hangfire;
using Hangfire.MySql;
using Microsoft.IdentityModel.Tokens;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundJobs.Hangfire;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using System.Threading.Tasks;
using CompanyName.ProjectName.Extensions;
using CompanyName.ProjectName.MultiTenancy;
using DefaultNamespace;
using DefaultNamespace.Swaggers;
using Lion.Abp.Cap;
using Savorboard.CAP.InMemoryMessageQueue;
using Serilog;
using Swashbuckle.AspNetCore.SwaggerUI;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.Caching;
namespace CompanyName.ProjectName
{
[DependsOn(
typeof(ProjectNameHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(ProjectNameApplicationModule),
typeof(ProjectNameEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAccountWebModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpBackgroundJobsHangfireModule),
typeof(LionAbpCapModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(SharedHostingMicroserviceModule)
)]
public class ProjectNameHttpApiHostModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
public override void OnPostApplicationInitialization(
ApplicationInitializationContext context)
{
// context.CreateRecurringJob();
base.OnPostApplicationInitialization(context);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
ConfigureCache(context);
ConfigureSwaggerServices(context, configuration);
ConfigureOptions(context);
ConfigureJwtAuthentication(context, configuration);
ConfigureHangfireMysql(context);
ConfigurationCap(context);
ConfigurationStsHttpClient(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var configuration = context.GetConfiguration();
app.UseAbpRequestLocalization();
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/ProjectName/swagger.json", "ProjectName API");
options.DocExpansion(DocExpansion.None);
options.DefaultModelsExpandDepth(-1);
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseSerilogRequestLogging(opts =>
{
opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest;
});
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); });
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
Authorization = new[] { new CustomHangfireAuthorizeFilter() },
IgnoreAntiforgeryToken = true
});
if (configuration.GetValue<bool>("Consul:Enabled", false))
{
app.UseConsul();
}
}
private void ConfigureHangfireMysql(ServiceConfigurationContext context)
{
Configure<AbpBackgroundJobOptions>(options =>
{
options.IsJobExecutionEnabled = true;
});
context.Services.AddHangfire(config =>
{
config.UseStorage(new MySqlStorage(
context.Services.GetConfiguration().GetConnectionString("Default"),
new MySqlStorageOptions()
{
//CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
//SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
//QueuePollInterval = TimeSpan.Zero,
//UseRecommendedIsolationLevel = true,
//DisableGlobalLocks = true
}));
});
}
/// <summary>
/// 配置JWT
/// </summary>
/// <param name="context"></param>
/// <param name="configuration"></param>
private void ConfigureJwtAuthentication(ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new Microsoft.IdentityModel.Tokens.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 accessToken = currentContext.Request.Query["access_token"];
// 如果请求来自signalr
var path = currentContext.HttpContext.Request.Path;
if (path.StartsWithSegments("/signalr"))
{
currentContext.Token = accessToken;
}
// 如果请求来自hangfire 或者cap
if (path.ToString().StartsWith("/hangfire") ||
path.ToString().StartsWith("/cap"))
{
currentContext.HttpContext.Response.Headers.Remove(
"X-Frame-Options");
if (!string.IsNullOrEmpty(accessToken))
{
currentContext.Token = accessToken;
currentContext.HttpContext.Response.Cookies
.Append("ProjectNameCookie", accessToken);
}
else
{
var cookies = currentContext.Request.Cookies;
if (cookies.ContainsKey("ProjectNameCookie"))
{
currentContext.Token = cookies["ProjectNameCookie"];
}
}
}
return Task.CompletedTask;
}
};
});
}
/// <summary>
/// 配置options
/// </summary>
/// <param name="context"></param>
private void ConfigureOptions(ServiceConfigurationContext context)
{
context.Services.Configure<JwtOptions>(context.Services.GetConfiguration()
.GetSection("Jwt"));
}
/// <summary>
/// Redis缓存
/// </summary>
private void ConfigureCache(ServiceConfigurationContext context)
{
Configure<AbpDistributedCacheOptions>(
options => { options.KeyPrefix = "ProjectName:"; });
var configuration = context.Services.GetConfiguration();
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
context.Services
.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "ProjectName-Protection-Keys");
}
private void ConfigurationStsHttpClient(ServiceConfigurationContext context)
{
context.Services.AddHttpClient(HttpClientNameConsts.Sts,
options =>
{
options.BaseAddress =
new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url")
.Value);
});
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(ProjectNameApplicationModule)
.Assembly);
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("ProjectName",
new OpenApiInfo { Title = "CompanyNameProjectName API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.EnableAnnotations(); // 启用注解
options.DocumentFilter<HiddenAbpDefaultApiFilter>();
options.SchemaFilter<EnumSchemaFilter>();
// 加载所有xml注释,这里会导致swagger加载有点缓慢
var xmls = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
foreach (var xml in xmls)
{
options.IncludeXmlComments(xml, true);
}
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme,
new OpenApiSecurityScheme()
{
Description =
"Please enter into field the word 'Bearer' followed by a space and the JWT value",
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<string>()
}
});
options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme()
{
Type = SecuritySchemeType.ApiKey,
In = ParameterLocation.Header,
Name = "Accept-Language",
Description = "多语言"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{ Type = ReferenceType.SecurityScheme, Id = "ApiKey" }
},
new string[] { }
}
});
});
}
private void ConfigurationCap(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var enabled = configuration.GetValue<bool>("Cap:Enabled", false);
if (enabled)
{
context.AddAbpCap(capOptions =>
{
capOptions.UseEntityFramework<ProjectNameDbContext>();
capOptions.UseRabbitMQ(option =>
{
option.HostName = configuration.GetValue<string>("Cap:RabbitMq:HostName");
option.UserName = configuration.GetValue<string>("Cap:RabbitMq:UserName");
option.Password = configuration.GetValue<string>("Cap:RabbitMq:Password");
});
var hostingEnvironment = context.Services.GetHostingEnvironment();
bool auth = !hostingEnvironment.IsDevelopment();
capOptions.UseDashboard(options => { options.UseAuth = auth; });
});
}
else
{
context.AddAbpCap(capOptions =>
{
capOptions.UseInMemoryStorage();
capOptions.UseInMemoryMessageQueue();
var hostingEnvironment = context.Services.GetHostingEnvironment();
bool auth = !hostingEnvironment.IsDevelopment();
capOptions.UseDashboard(options => { options.UseAuth = auth; });
});
}
}
}
}