JiShe.IOT.Admin/host/JiShe.IoT.HttpApi.Host/IoTHttpApiHostModule.Configure.cs

342 lines
14 KiB
C#
Raw Normal View History

2025-05-27 14:02:24 +08:00
using Hangfire.Redis.StackExchange;
2025-06-09 11:28:33 +08:00
using JiShe.ServicePro.FreeRedisProvider;
2025-06-18 16:04:41 +08:00
using JiShe.ServicePro.SwaggerConfigs;
2025-05-27 14:02:24 +08:00
using Medallion.Threading;
using Medallion.Threading.Redis;
2025-06-18 16:04:41 +08:00
using Microsoft.CodeAnalysis;
2025-05-27 22:53:46 +08:00
using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem;
2025-05-27 14:02:24 +08:00
2025-05-27 14:27:50 +08:00
namespace JiShe.IoT;
2025-05-27 14:02:24 +08:00
2025-05-27 14:27:50 +08:00
public partial class IoTHttpApiHostModule
2025-05-27 14:02:24 +08:00
{
private void ConfigureHangfire(ServiceConfigurationContext context)
{
var redisStorageOptions = new RedisStorageOptions()
{
Db = context.Services.GetConfiguration().GetValue<int>("Hangfire:Redis:DB")
};
Configure<AbpBackgroundJobOptions>(options => { options.IsJobExecutionEnabled = true; });
context.Services.AddHangfire(config =>
{
config.UseRedisStorage(
context.Services.GetConfiguration().GetValue<string>("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));
});
}
/// <summary>
/// 配置MiniProfiler
/// </summary>
private void ConfigureMiniProfiler(ServiceConfigurationContext context)
{
if (context.Services.GetConfiguration().GetValue("MiniProfiler:Enabled", false))
{
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"]))
};
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())
{
2025-05-27 14:27:50 +08:00
accessToken = currentContext.Request.Cookies[IoTHttpApiHostConst.DefaultCookieName];
2025-05-27 14:02:24 +08:00
}
currentContext.Token = accessToken;
currentContext.Request.Headers.Remove("Authorization");
currentContext.Request.Headers.Append("Authorization", $"Bearer {accessToken}");
return Task.CompletedTask;
}
};
});
}
/// <summary>
/// Redis缓存
/// </summary>
private void ConfigureCache(ServiceConfigurationContext context)
{
Configure<AbpDistributedCacheOptions>(
2025-06-09 10:47:25 +08:00
options => { options.KeyPrefix = "JiSheIoT:"; });
2025-05-27 14:02:24 +08:00
var configuration = context.Services.GetConfiguration();
2025-07-28 17:10:05 +08:00
2025-05-27 14:02:24 +08:00
context.Services
.AddDataProtection()
2025-07-07 13:36:31 +08:00
.PersistKeysToStackFreeRedis($"{RedisConst.CachePersistKeys}JiSheIoTAdmin-Protection-Keys");
2025-05-27 14:02:24 +08:00
}
/// <summary>
/// 配置Identity
/// </summary>
private void ConfigureIdentity(ServiceConfigurationContext context)
{
context.Services.Configure<IdentityOptions>(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; });
}
private void ConfigurationSignalR(ServiceConfigurationContext context)
{
context.Services
.AddSignalR()
.AddStackExchangeRedis(context.Services.GetConfiguration().GetValue<string>("Redis:Configuration"),
options => { options.Configuration.ChannelPrefix = "JiShe.ServicePro"; });
}
private void ConfigureSwaggerServices(ServiceConfigurationContext context)
{
context.Services.AddSwaggerGen(
options =>
{
// 文件下载类型
2025-12-07 20:21:24 +08:00
options.MapType<FileContentResult>(() => new OpenApiSchema() { Type = "file" });
2025-05-27 14:02:24 +08:00
2025-07-28 17:10:05 +08:00
options.SwaggerDoc("AbpPro", new OpenApiInfo { Title = "AbpPro API", Version = "v1" });
2025-06-18 16:04:41 +08:00
var configuration = context.Services.GetConfiguration();
2025-12-07 20:21:24 +08:00
var groupNames = EnumExtensions.GetEnumTypeValueNameList<SwaggerGroupEnum>();
2025-06-19 11:36:07 +08:00
var excludeSwaggerGroups = configuration.GetSection("ExcludeSwaggerGroup").Get<List<string>>() ?? new List<string>();
2025-06-18 16:04:41 +08:00
groupNames.ForEach(group =>
{
2025-06-19 11:36:07 +08:00
if (!excludeSwaggerGroups.Where(e => e == group.Key).Any())
{
options.SwaggerDoc(group.Key,
new OpenApiInfo { Title = group.Value, Version = "v1" });
}
2025-06-18 16:04:41 +08:00
});
2025-07-28 17:10:05 +08:00
options.DocInclusionPredicate((docName, description) =>
{
if (docName == "AbpPro")
{
return true;
}
2025-06-18 16:04:41 +08:00
return description.GroupName == docName;
});
2025-07-28 17:10:05 +08:00
2025-06-23 10:55:41 +08:00
//options.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true); // 启用注解
2025-05-27 14:02:24 +08:00
options.DocumentFilter<HiddenAbpDefaultApiFilter>();
options.SchemaFilter<EnumSchemaFilter>();
// 加载所有xml注释这里会导致swagger加载有点缓慢
var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
foreach (var xml in xmlPaths)
{
options.IncludeXmlComments(xml, true);
}
2025-06-18 16:04:41 +08:00
// 加载 模块引入的xml注释
// 加载所有xml注释这里会导致swagger加载有点缓慢
var modulePath = Path.Combine(AppContext.BaseDirectory, "moduleSwagger");
if (Directory.Exists(modulePath))
{
var xmlModulePaths = Directory.GetFiles(modulePath, "*.xml");
foreach (var xml in xmlModulePaths)
{
options.IncludeXmlComments(xml, true);
}
}
2025-05-27 14:02:24 +08:00
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme,
new OpenApiSecurityScheme()
{
Description = "直接在下框输入JWT生成的Token",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT"
});
2025-12-07 20:21:24 +08:00
options.AddSecurityRequirement(new OpenApiSecurityRequirement
2025-05-27 14:02:24 +08:00
{
2025-12-07 20:21:24 +08:00
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme, Id = "Bearer"
}
},
new List<string>()
}
2025-05-27 14:02:24 +08:00
});
options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme()
{
Type = SecuritySchemeType.ApiKey,
In = ParameterLocation.Header,
Name = "Accept-Language",
Description = "多语言设置系统预设语言有zh-Hans、en默认为zh-Hans",
});
2025-12-07 20:21:24 +08:00
options.AddSecurityRequirement(new OpenApiSecurityRequirement
2025-05-27 14:02:24 +08:00
{
{
2025-12-07 20:21:24 +08:00
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{ Type = ReferenceType.SecurityScheme, Id = "ApiKey" }
},
Array.Empty<string>()
2025-05-27 14:02:24 +08:00
}
});
});
}
private void ConfigureCap(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.AddAbpCap(capOptions =>
{
capOptions.SetCapDbConnectionString(configuration["ConnectionStrings:Default"]);
2025-05-27 14:27:50 +08:00
capOptions.UseEntityFramework<IoTDbContext>();
2025-05-27 14:02:24 +08:00
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");
option.Port = configuration.GetValue<int>("Cap:RabbitMq:Port");
});
capOptions.UseDashboard(options =>
{
options.AuthorizationPolicy = ServiceProCapPermissions.CapManagement.Cap;
});
});
}
/// <summary>
/// 审计日志
/// </summary>
private void ConfigureAuditLog(ServiceConfigurationContext context)
{
Configure<AbpAuditingOptions>
(
options =>
{
options.IsEnabled = true;
EntityHistorySelectorListExtensions.AddAllEntities(options.EntityHistorySelectors);
options.ApplicationName = "JiShe.ServicePro";
}
);
Configure<AbpAspNetCoreAuditingOptions>(
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<AbpMultiTenancyOptions>(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; });
}
/// <summary>
/// 配置redis分布式锁
/// </summary>
private void ConfigurationDistributedLocking(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var connectionString = configuration.GetValue<string>("Redis:Configuration");
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(connectionString);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
2025-05-27 22:53:46 +08:00
/// <summary>
/// 配置 文件管理的 blob设置默认使用本地文件系统
/// </summary>
private void ConfigureBlobStorage()
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseFileSystem(fileSystem =>
{
string[] filePathArray = new string[] {
Environment.CurrentDirectory,
"UploadFile",
DateTime.Now.Date.ToString("yyyyMMdd")
};
string filePath = Path.Combine(filePathArray);
//检查文件夹是否存在
if (!System.IO.Directory.Exists(filePath))
{
System.IO.Directory.CreateDirectory(filePath);
}
fileSystem.BasePath = filePath;
});
});
});
}
2025-05-27 14:02:24 +08:00
}