8 changed files with 275 additions and 238 deletions
@ -1,268 +1,273 @@ |
|||
namespace MyCompanyName.MyProjectName |
|||
namespace MyCompanyName.MyProjectName; |
|||
|
|||
[DependsOn( |
|||
typeof(MyProjectNameHttpApiModule), |
|||
typeof(AbpProSharedHostingMicroserviceModule), |
|||
typeof(AbpAspNetCoreMvcUiMultiTenancyModule), |
|||
typeof(MyProjectNameEntityFrameworkCoreModule), |
|||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
|||
typeof(AbpAspNetCoreSerilogModule), |
|||
typeof(AbpAccountWebModule), |
|||
typeof(MyProjectNameApplicationModule), |
|||
typeof(AbpAspNetCoreMvcUiBasicThemeModule), |
|||
typeof(AbpCachingStackExchangeRedisModule) |
|||
)] |
|||
public class MyProjectNameHttpApiHostModule : AbpModule |
|||
{ |
|||
[DependsOn( |
|||
typeof(MyProjectNameHttpApiModule), |
|||
typeof(AbpProSharedHostingMicroserviceModule), |
|||
typeof(AbpAspNetCoreMvcUiMultiTenancyModule), |
|||
typeof(MyProjectNameEntityFrameworkCoreModule), |
|||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
|||
typeof(AbpAspNetCoreSerilogModule), |
|||
typeof(AbpAccountWebModule), |
|||
typeof(MyProjectNameApplicationModule), |
|||
typeof(AbpAspNetCoreMvcUiBasicThemeModule), |
|||
typeof(AbpCachingStackExchangeRedisModule) |
|||
)] |
|||
public class MyProjectNameHttpApiHostModule : AbpModule |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
ConfigureCache(context); |
|||
ConfigureSwaggerServices(context); |
|||
ConfigureJwtAuthentication(context, configuration); |
|||
ConfigureMiniProfiler(context); |
|||
ConfigureIdentity(context); |
|||
ConfigureAuditLog(context); |
|||
ConfigurationSignalR(context); |
|||
ConfigurationMultiTenancy(); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
app.UseAbpRequestLocalization(); |
|||
app.UseCorrelationId(); |
|||
app.UseStaticFiles(); |
|||
app.UseMiniProfiler(); |
|||
app.UseRouting(); |
|||
app.UseCors(MyProjectNameHttpApiHostConst.DefaultCorsPolicyName); |
|||
app.UseAuthentication(); |
|||
|
|||
if (MultiTenancyConsts.IsEnabled) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
ConfigureCache(context); |
|||
ConfigureSwaggerServices(context); |
|||
ConfigureJwtAuthentication(context, configuration); |
|||
ConfigureMiniProfiler(context); |
|||
ConfigureIdentity(context); |
|||
ConfigureAuditLog(context); |
|||
ConfigurationSignalR(context); |
|||
app.UseMultiTenancy(); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
app.UseAuthorization(); |
|||
app.UseSwagger(); |
|||
app.UseAbpSwaggerUI(options => |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
app.UseAbpRequestLocalization(); |
|||
app.UseCorrelationId(); |
|||
app.UseStaticFiles(); |
|||
app.UseMiniProfiler(); |
|||
app.UseRouting(); |
|||
app.UseCors(MyProjectNameHttpApiHostConst.DefaultCorsPolicyName); |
|||
app.UseAuthentication(); |
|||
|
|||
if (MultiTenancyConsts.IsEnabled) |
|||
{ |
|||
app.UseMultiTenancy(); |
|||
} |
|||
options.SwaggerEndpoint("/swagger/MyProjectName/swagger.json", "MyProjectName API"); |
|||
options.DocExpansion(DocExpansion.None); |
|||
options.DefaultModelsExpandDepth(-1); |
|||
}); |
|||
|
|||
app.UseAuthorization(); |
|||
app.UseSwagger(); |
|||
app.UseAbpSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/MyProjectName/swagger.json", "MyProjectName API"); |
|||
options.DocExpansion(DocExpansion.None); |
|||
options.DefaultModelsExpandDepth(-1); |
|||
}); |
|||
app.UseAuditing(); |
|||
app.UseAbpSerilogEnrichers(); |
|||
|
|||
app.UseAuditing(); |
|||
app.UseAbpSerilogEnrichers(); |
|||
app.UseUnitOfWork(); |
|||
app.UseConfiguredEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); |
|||
|
|||
app.UseUnitOfWork(); |
|||
app.UseConfiguredEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); |
|||
} |
|||
private void ConfigurationSignalR(ServiceConfigurationContext context) |
|||
{ |
|||
var redisConnection = context.Services.GetConfiguration()["Redis:Configuration"]; |
|||
|
|||
} |
|||
private void ConfigurationSignalR(ServiceConfigurationContext context) |
|||
if (redisConnection.IsNullOrWhiteSpace()) |
|||
{ |
|||
var redisConnection = context.Services.GetConfiguration()["Redis:Configuration"]; |
|||
throw new UserFriendlyException(message: "Redis连接字符串未配置."); |
|||
} |
|||
|
|||
if (redisConnection.IsNullOrWhiteSpace()) |
|||
{ |
|||
throw new UserFriendlyException(message: "Redis连接字符串未配置."); |
|||
} |
|||
context.Services.AddSignalR().AddStackExchangeRedis(redisConnection, options => { options.Configuration.ChannelPrefix = "Lion.AbpPro"; }); |
|||
} |
|||
/// <summary>
|
|||
/// 配置MiniProfiler
|
|||
/// </summary>
|
|||
private void ConfigureMiniProfiler(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler").AddEntityFramework(); |
|||
} |
|||
|
|||
context.Services.AddSignalR().AddStackExchangeRedis(redisConnection, options => { options.Configuration.ChannelPrefix = "Lion.AbpPro"; }); |
|||
} |
|||
/// <summary>
|
|||
/// 配置MiniProfiler
|
|||
/// </summary>
|
|||
private void ConfigureMiniProfiler(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler").AddEntityFramework(); |
|||
} |
|||
/// <summary>
|
|||
/// 配置JWT
|
|||
/// </summary>
|
|||
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"])) |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// 配置JWT
|
|||
/// </summary>
|
|||
private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) |
|||
{ |
|||
context.Services.AddAuthentication(options => |
|||
{ |
|||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; |
|||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; |
|||
}) |
|||
.AddJwtBearer(options => |
|||
options.Events = new JwtBearerEvents |
|||
{ |
|||
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 => |
|||
{ |
|||
OnMessageReceived = currentContext => |
|||
var path = currentContext.HttpContext.Request.Path; |
|||
if (path.StartsWithSegments("/login")) |
|||
{ |
|||
var path = currentContext.HttpContext.Request.Path; |
|||
if (path.StartsWithSegments("/login")) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
var accessToken = string.Empty; |
|||
if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) |
|||
var accessToken = string.Empty; |
|||
if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) |
|||
{ |
|||
accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; |
|||
if (!string.IsNullOrWhiteSpace(accessToken)) |
|||
{ |
|||
accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; |
|||
if (!string.IsNullOrWhiteSpace(accessToken)) |
|||
{ |
|||
accessToken = accessToken.Split(" ").LastOrDefault(); |
|||
} |
|||
accessToken = accessToken.Split(" ").LastOrDefault(); |
|||
} |
|||
} |
|||
|
|||
if (accessToken.IsNullOrWhiteSpace()) |
|||
{ |
|||
accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); |
|||
} |
|||
if (accessToken.IsNullOrWhiteSpace()) |
|||
{ |
|||
accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); |
|||
} |
|||
|
|||
if (accessToken.IsNullOrWhiteSpace()) |
|||
{ |
|||
accessToken = currentContext.Request.Cookies[MyProjectNameHttpApiHostConst.DefaultCookieName]; |
|||
} |
|||
if (accessToken.IsNullOrWhiteSpace()) |
|||
{ |
|||
accessToken = currentContext.Request.Cookies[MyProjectNameHttpApiHostConst.DefaultCookieName]; |
|||
} |
|||
|
|||
currentContext.Token = accessToken; |
|||
currentContext.Request.Headers.Remove("Authorization"); |
|||
currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); |
|||
currentContext.Token = accessToken; |
|||
currentContext.Request.Headers.Remove("Authorization"); |
|||
currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
}; |
|||
}); |
|||
} |
|||
return Task.CompletedTask; |
|||
} |
|||
}; |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// Redis缓存
|
|||
/// </summary>
|
|||
private void ConfigureCache(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpDistributedCacheOptions>( |
|||
options => { options.KeyPrefix = "MyProjectName:"; }); |
|||
var configuration = context.Services.GetConfiguration(); |
|||
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
|||
context.Services |
|||
.AddDataProtection() |
|||
.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys"); |
|||
} |
|||
/// <summary>
|
|||
/// Redis缓存
|
|||
/// </summary>
|
|||
private void ConfigureCache(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpDistributedCacheOptions>( |
|||
options => { options.KeyPrefix = "MyProjectName:"; }); |
|||
var configuration = context.Services.GetConfiguration(); |
|||
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
|||
context.Services |
|||
.AddDataProtection() |
|||
.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys"); |
|||
} |
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 配置Identity
|
|||
/// </summary>
|
|||
private void ConfigureIdentity(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.Configure<IdentityOptions>(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); |
|||
} |
|||
/// <summary>
|
|||
/// 配置Identity
|
|||
/// </summary>
|
|||
private void ConfigureIdentity(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.Configure<IdentityOptions>(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); |
|||
} |
|||
|
|||
private static void ConfigureSwaggerServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddSwaggerGen( |
|||
options => |
|||
{ |
|||
// 文件下载类型
|
|||
options.MapType<FileContentResult>(() => new OpenApiSchema() { Type = "file" }); |
|||
|
|||
options.SwaggerDoc("MyProjectName", |
|||
new OpenApiInfo { Title = "MyCompanyNameMyProjectName API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.EnableAnnotations(); // 启用注解
|
|||
options.DocumentFilter<HiddenAbpDefaultApiFilter>(); |
|||
options.SchemaFilter<EnumSchemaFilter>(); |
|||
// 加载所有xml注释,这里会导致swagger加载有点缓慢
|
|||
var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); |
|||
foreach (var xml in xmlPaths) |
|||
{ |
|||
options.IncludeXmlComments(xml, true); |
|||
} |
|||
private static void ConfigureSwaggerServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddSwaggerGen( |
|||
options => |
|||
{ |
|||
// 文件下载类型
|
|||
options.MapType<FileContentResult>(() => new OpenApiSchema() { Type = "file" }); |
|||
|
|||
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<string>() |
|||
} |
|||
}); |
|||
options.SwaggerDoc("MyProjectName", |
|||
new OpenApiInfo { Title = "MyCompanyNameMyProjectName API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.EnableAnnotations(); // 启用注解
|
|||
options.DocumentFilter<HiddenAbpDefaultApiFilter>(); |
|||
options.SchemaFilter<EnumSchemaFilter>(); |
|||
// 加载所有xml注释,这里会导致swagger加载有点缓慢
|
|||
var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); |
|||
foreach (var xml in xmlPaths) |
|||
{ |
|||
options.IncludeXmlComments(xml, true); |
|||
} |
|||
|
|||
options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() |
|||
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, |
|||
new OpenApiSecurityScheme() |
|||
{ |
|||
Type = SecuritySchemeType.ApiKey, |
|||
Description = "直接在下框输入JWT生成的Token", |
|||
Name = "Authorization", |
|||
In = ParameterLocation.Header, |
|||
Name = "Accept-Language", |
|||
Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans", |
|||
Type = SecuritySchemeType.Http, |
|||
Scheme = JwtBearerDefaults.AuthenticationScheme, |
|||
BearerFormat = "JWT" |
|||
}); |
|||
|
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
Reference = new OpenApiReference |
|||
{ |
|||
Reference = new OpenApiReference |
|||
{ Type = ReferenceType.SecurityScheme, Id = "ApiKey" } |
|||
}, |
|||
Array.Empty<string>() |
|||
} |
|||
}); |
|||
Type = ReferenceType.SecurityScheme, Id = "Bearer" |
|||
} |
|||
}, |
|||
new List<string>() |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 审计日志
|
|||
/// </summary>
|
|||
private void ConfigureAuditLog(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpAuditingOptions> |
|||
( |
|||
options => |
|||
options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() |
|||
{ |
|||
options.IsEnabled = true; |
|||
options.EntityHistorySelectors.AddAllEntities(); |
|||
options.ApplicationName = "MyCompanyName.MyProjectName"; |
|||
} |
|||
); |
|||
Type = SecuritySchemeType.ApiKey, |
|||
In = ParameterLocation.Header, |
|||
Name = "Accept-Language", |
|||
Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans", |
|||
}); |
|||
|
|||
Configure<AbpAspNetCoreAuditingOptions>( |
|||
options => |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
options.IgnoredUrls.Add("/AuditLogs/page"); |
|||
options.IgnoredUrls.Add("/hangfire/stats"); |
|||
options.IgnoredUrls.Add("/cap"); |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
Reference = new OpenApiReference |
|||
{ Type = ReferenceType.SecurityScheme, Id = "ApiKey" } |
|||
}, |
|||
Array.Empty<string>() |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 审计日志
|
|||
/// </summary>
|
|||
private void ConfigureAuditLog(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpAuditingOptions> |
|||
( |
|||
options => |
|||
{ |
|||
options.IsEnabled = true; |
|||
options.EntityHistorySelectors.AddAllEntities(); |
|||
options.ApplicationName = "MyCompanyName.MyProjectName"; |
|||
} |
|||
); |
|||
|
|||
Configure<AbpAspNetCoreAuditingOptions>( |
|||
options => |
|||
{ |
|||
options.IgnoredUrls.Add("/AuditLogs/page"); |
|||
options.IgnoredUrls.Add("/hangfire/stats"); |
|||
options.IgnoredUrls.Add("/cap"); |
|||
}); |
|||
} |
|||
|
|||
private void ConfigurationMultiTenancy() |
|||
{ |
|||
Configure<AbpMultiTenancyOptions>(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue