BusinessHostModule.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. using Business.EntityFrameworkCore;
  2. using Business.MultiTenancy;
  3. using Hangfire;
  4. using Hangfire.Dashboard.BasicAuthorization;
  5. using Hangfire.MySql;
  6. using Hangfire.MySql.Core;
  7. using Microsoft.AspNetCore.Authentication.JwtBearer;
  8. using Microsoft.AspNetCore.Builder;
  9. using Microsoft.AspNetCore.Cors;
  10. using Microsoft.AspNetCore.DataProtection;
  11. using Microsoft.AspNetCore.Hosting;
  12. using Microsoft.Extensions.Configuration;
  13. using Microsoft.Extensions.DependencyInjection;
  14. using Microsoft.Extensions.Hosting;
  15. using Microsoft.OpenApi.Models;
  16. using StackExchange.Redis;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Data;
  20. using System.IO;
  21. using System.Linq;
  22. using Volo.Abp;
  23. using Volo.Abp.AspNetCore.MultiTenancy;
  24. using Volo.Abp.AspNetCore.Mvc;
  25. using Volo.Abp.AspNetCore.Serilog;
  26. using Volo.Abp.Autofac;
  27. using Volo.Abp.Caching;
  28. using Volo.Abp.Data;
  29. using Volo.Abp.EntityFrameworkCore.MySQL;
  30. using Volo.Abp.Localization;
  31. using Volo.Abp.Modularity;
  32. using Volo.Abp.MultiTenancy;
  33. using Volo.Abp.Threading;
  34. using Volo.Abp.VirtualFileSystem;
  35. namespace Business
  36. {
  37. [DependsOn(
  38. typeof(AbpAutofacModule),
  39. typeof(AbpEntityFrameworkCoreMySQLModule),
  40. typeof(BusinessHttpApiModule),
  41. typeof(BusinessApplicationModule),
  42. typeof(BusinessEntityFrameworkCoreModule),
  43. typeof(AbpAspNetCoreMultiTenancyModule),
  44. typeof(AbpAspNetCoreSerilogModule)
  45. )]
  46. public class BusinessHostModule : AbpModule
  47. {
  48. private const string DefaultCorsPolicyName = "Default";
  49. public override void ConfigureServices(ServiceConfigurationContext context)
  50. {
  51. var configuration = context.Services.GetConfiguration();
  52. var hostingEnvironment = context.Services.GetHostingEnvironment();
  53. //ConfigureConventionalControllers();
  54. ConfigureMultiTenancy();
  55. ConfigureAuthentication(context, configuration);
  56. ConfigureLocalization();
  57. ConfigureCache(configuration);
  58. ConfigureVirtualFileSystem(context, hostingEnvironment);
  59. //ConfigureRedis(context, configuration, hostingEnvironment);
  60. ConfigureCors(context, configuration);
  61. ConfigureSwaggerServices(context, configuration);
  62. ConfigureHangfire(context, configuration);
  63. }
  64. private void ConfigureConventionalControllers()
  65. {
  66. Configure<AbpAspNetCoreMvcOptions>(options =>
  67. {
  68. options.ConventionalControllers.Create(typeof(BusinessApplicationModule).Assembly);
  69. });
  70. }
  71. private void ConfigureMultiTenancy()
  72. {
  73. Configure<AbpMultiTenancyOptions>(options =>
  74. {
  75. options.IsEnabled = true;
  76. });
  77. }
  78. private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
  79. {
  80. context.Services.AddHangfire(config =>
  81. {
  82. //config.UseStorage(new MySqlStorage(configuration.GetConnectionString("Business"),new MySqlStorageOptions
  83. //{
  84. // TransactionIsolationLevel =IsolationLevel.ReadCommitted,
  85. // QueuePollInterval = TimeSpan.FromSeconds(15),
  86. // JobExpirationCheckInterval = TimeSpan.FromHours(1),
  87. // CountersAggregateInterval = TimeSpan.FromMinutes(5),
  88. // PrepareSchemaIfNecessary = true,
  89. // DashboardJobListLimit = 50000,
  90. // TransactionTimeout = TimeSpan.FromMinutes(1),
  91. // TablePrefix = "Hangfire"
  92. //}));
  93. config.UseStorage(new MySqlStorage(configuration.GetConnectionString("Business")));
  94. });
  95. }
  96. private void ConfigureCache(IConfiguration configuration)
  97. {
  98. Configure<AbpDistributedCacheOptions>(options =>
  99. {
  100. options.KeyPrefix = "Business:";
  101. });
  102. }
  103. private void ConfigureVirtualFileSystem(ServiceConfigurationContext context, IWebHostEnvironment webHostEnvironment)
  104. {
  105. //var hostingEnvironment = context.Services.GetHostingEnvironment();
  106. if (webHostEnvironment.IsDevelopment())
  107. {
  108. Configure<AbpVirtualFileSystemOptions>(options =>
  109. {
  110. options.FileSets.ReplaceEmbeddedByPhysical<BusinessDomainModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Domain"));
  111. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationContractsModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application.Contracts"));
  112. options.FileSets.ReplaceEmbeddedByPhysical<BusinessApplicationModule>(Path.Combine(webHostEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Business.Application"));
  113. });
  114. }
  115. }
  116. private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
  117. {
  118. context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  119. .AddJwtBearer(options =>
  120. {
  121. options.Authority = configuration["AuthServer:Authority"];
  122. options.RequireHttpsMetadata = false;
  123. options.Audience = "BusinessService";
  124. });
  125. }
  126. private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
  127. {
  128. if (configuration["UseSwagger"] == "true")
  129. {
  130. context.Services.AddSwaggerGen(options =>
  131. {
  132. options.SwaggerDoc("v1", new OpenApiInfo { Title = "Business Service API", Version = "v1" });
  133. options.DocInclusionPredicate((docName, description) => true);
  134. options.CustomSchemaIds(type => type.FullName);
  135. options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
  136. {
  137. Description = "请输入JWT令牌,例如:Bearer 12345abcdef",
  138. Name = "Authorization",
  139. In = ParameterLocation.Header,
  140. Type = SecuritySchemeType.ApiKey,
  141. Scheme = "Bearer"
  142. });
  143. options.AddSecurityRequirement(new OpenApiSecurityRequirement()
  144. {
  145. {
  146. new OpenApiSecurityScheme
  147. {
  148. Reference = new OpenApiReference
  149. {
  150. Type = ReferenceType.SecurityScheme,
  151. Id = "Bearer"
  152. },
  153. Scheme = "oauth2",
  154. Name = "Bearer",
  155. In = ParameterLocation.Header,
  156. },
  157. new List<string>()
  158. }
  159. });
  160. });
  161. }
  162. }
  163. private void ConfigureLocalization()
  164. {
  165. Configure<AbpLocalizationOptions>(options =>
  166. {
  167. options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
  168. options.Languages.Add(new LanguageInfo("en", "en", "English"));
  169. options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
  170. options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
  171. options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
  172. options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
  173. });
  174. }
  175. private void ConfigureRedis(
  176. ServiceConfigurationContext context,
  177. IConfiguration configuration,
  178. IWebHostEnvironment hostingEnvironment)
  179. {
  180. context.Services.AddStackExchangeRedisCache(options =>
  181. {
  182. options.Configuration = configuration["Redis:Configuration"];
  183. });
  184. if (!hostingEnvironment.IsDevelopment())
  185. {
  186. var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
  187. context.Services
  188. .AddDataProtection()
  189. .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
  190. }
  191. }
  192. private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
  193. {
  194. context.Services.AddCors(options =>
  195. {
  196. options.AddPolicy(DefaultCorsPolicyName, builder =>
  197. {
  198. builder
  199. .WithOrigins(
  200. configuration["App:CorsOrigins"]
  201. .Split(",", StringSplitOptions.RemoveEmptyEntries)
  202. .Select(o => o.RemovePostFix("/"))
  203. .ToArray()
  204. )
  205. .WithAbpExposedHeaders()
  206. .SetIsOriginAllowedToAllowWildcardSubdomains()
  207. .AllowAnyHeader()
  208. .AllowAnyMethod()
  209. .AllowCredentials();
  210. });
  211. });
  212. }
  213. public override void OnApplicationInitialization(ApplicationInitializationContext context)
  214. {
  215. var app = context.GetApplicationBuilder();
  216. var configuration = context.GetConfiguration();
  217. app.UseCorrelationId();
  218. app.UseStaticFiles();
  219. app.UseRouting();
  220. app.UseCors(DefaultCorsPolicyName);
  221. app.UseAuthentication();
  222. app.UseAbpClaimsMap();
  223. if (MultiTenancyConsts.IsEnabled)
  224. {
  225. app.UseMultiTenancy();
  226. }
  227. app.UseAbpRequestLocalization();
  228. if (configuration["UseSwagger"] == "true")
  229. {
  230. app.UseSwagger();
  231. app.UseSwaggerUI(options =>
  232. {
  233. options.SwaggerEndpoint("/swagger/v1/swagger.json", "Business Service API");
  234. });
  235. }
  236. app.UseAuditing();
  237. app.UseAbpSerilogEnrichers();
  238. app.UseUnitOfWork();
  239. app.UseConfiguredEndpoints();
  240. //app.UseHangfireServer();
  241. app.UseHangfireDashboard(options: new DashboardOptions
  242. {
  243. Authorization = new[]
  244. {
  245. new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions
  246. {
  247. RequireSsl = false,
  248. SslRedirect = false,
  249. LoginCaseSensitive = true,
  250. Users = new []
  251. {
  252. new BasicAuthAuthorizationUser
  253. {
  254. Login = configuration["Hangfire:Login"],
  255. PasswordClear = configuration["Hangfire:Password"]
  256. }
  257. }
  258. })
  259. },
  260. DashboardTitle = "任务调度中心"
  261. });
  262. AsyncHelper.RunSync(async () =>
  263. {
  264. using (var scope = context.ServiceProvider.CreateScope())
  265. {
  266. await scope.ServiceProvider
  267. .GetRequiredService<IDataSeeder>()
  268. .SeedAsync();
  269. }
  270. });
  271. }
  272. }
  273. }