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.

518 lines
19 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
2 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Microsoft.AspNetCore.Builder;
  6. using Microsoft.AspNetCore.Cors;
  7. using Microsoft.AspNetCore.Extensions.DependencyInjection;
  8. using Microsoft.Extensions.Configuration;
  9. using Microsoft.Extensions.DependencyInjection;
  10. using Microsoft.Extensions.Hosting;
  11. using Shentun.Peis.EntityFrameworkCore;
  12. using Shentun.Peis.MultiTenancy;
  13. using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite;
  14. using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling;
  15. using Microsoft.OpenApi.Models;
  16. using OpenIddict.Validation.AspNetCore;
  17. using Volo.Abp;
  18. using Volo.Abp.Account;
  19. using Volo.Abp.Account.Web;
  20. using Volo.Abp.AspNetCore.MultiTenancy;
  21. using Volo.Abp.AspNetCore.Mvc;
  22. using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
  23. using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
  24. using Volo.Abp.AspNetCore.Serilog;
  25. using Volo.Abp.Autofac;
  26. using Volo.Abp.Localization;
  27. using Volo.Abp.Modularity;
  28. using Volo.Abp.Swashbuckle;
  29. using Volo.Abp.UI.Navigation.Urls;
  30. using Volo.Abp.VirtualFileSystem;
  31. using Microsoft.AspNetCore.Mvc;
  32. using Microsoft.Extensions.Options;
  33. using System.Reflection;
  34. using Swashbuckle.AspNetCore.SwaggerGen;
  35. using Microsoft.AspNetCore.Mvc.Filters;
  36. using TencentCloud.Dts.V20211206.Models;
  37. using Volo.Abp.AspNetCore.Mvc.Validation;
  38. using Microsoft.Extensions.DependencyInjection.Extensions;
  39. using Volo.Abp.Identity;
  40. using Microsoft.Extensions.FileProviders;
  41. using Microsoft.AspNetCore.Mvc.ApplicationModels;
  42. using Volo.Abp.Settings;
  43. using Volo.Abp.Identity.Settings;
  44. using Microsoft.AspNetCore.Identity;
  45. using Volo.Abp.AspNetCore.Mvc.AntiForgery;
  46. using Microsoft.AspNetCore.Authentication;
  47. using Nito.Disposables.Internals;
  48. using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
  49. using static IdentityModel.ClaimComparer;
  50. using Microsoft.AspNetCore.Authorization;
  51. using Microsoft.AspNetCore.Diagnostics;
  52. using Microsoft.AspNetCore.Http;
  53. using Shentun.Peis.Filter;
  54. using Shentun.Peis.VirtualPath;
  55. using System.Text.Encodings.Web;
  56. using System.Text.Unicode;
  57. using Volo.Abp.Json;
  58. namespace Shentun.Peis;
  59. [DependsOn(
  60. typeof(PeisHttpApiModule),
  61. typeof(AbpAutofacModule),
  62. typeof(AbpAspNetCoreMultiTenancyModule),
  63. typeof(PeisApplicationModule),
  64. typeof(PeisEntityFrameworkCoreModule),
  65. typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule),
  66. typeof(AbpAccountWebOpenIddictModule),
  67. typeof(AbpAspNetCoreSerilogModule),
  68. typeof(AbpSwashbuckleModule)
  69. )]
  70. public class PeisHttpApiHostModule : AbpModule
  71. {
  72. public override void PreConfigureServices(ServiceConfigurationContext context)
  73. {
  74. PreConfigure<OpenIddictBuilder>(builder =>
  75. {
  76. builder.AddValidation(options =>
  77. {
  78. options.AddAudiences("Peis");
  79. options.UseLocalServer();
  80. options.UseAspNetCore();
  81. });
  82. });
  83. //重写定义token失效时间 接口返回的是秒
  84. PreConfigure<OpenIddictServerBuilder>(builder =>
  85. {
  86. //builder.SetAccessTokenLifetime(TimeSpan.FromHours(8)).SetRefreshTokenLifetime(TimeSpan.FromDays(15));
  87. builder.SetAccessTokenLifetime(TimeSpan.FromDays(30)).SetRefreshTokenLifetime(TimeSpan.FromDays(60));
  88. });
  89. }
  90. public override void ConfigureServices(ServiceConfigurationContext context)
  91. {
  92. var configuration = context.Services.GetConfiguration();
  93. var hostingEnvironment = context.Services.GetHostingEnvironment();
  94. ConfigureAuthentication(context);
  95. ConfigureBundles();
  96. ConfigureUrls(configuration);
  97. ConfigureConventionalControllers();
  98. ConfigureLocalization();
  99. ConfigureVirtualFileSystem(context);
  100. ConfigureCors(context, configuration);
  101. ConfigureSwaggerServices(context, configuration);
  102. ConfigureJsonOptions(); //全局配置api返回值中的日期默认格式
  103. //密码策略配置
  104. context.Services.Configure<IdentityOptions>(opt =>
  105. {
  106. opt.Password.RequireDigit = false;
  107. opt.Password.RequireLowercase = false;
  108. opt.Password.RequireUppercase = false;
  109. opt.Password.RequireNonAlphanumeric = false;
  110. opt.Password.RequiredLength = 6;
  111. });
  112. //防伪令牌
  113. //context.Services.Configure<AbpAntiForgeryOptions>(opt =>
  114. //{
  115. // opt.AutoValidate = false;
  116. //});
  117. context.Services.AddMvc(options =>
  118. {
  119. var filterMetadata = options.Filters.FirstOrDefault(x => x is ServiceFilterAttribute attribute && attribute.ServiceType.Equals(typeof(AbpValidationActionFilter)));
  120. options.Filters.Remove(filterMetadata);
  121. options.Filters.Add(typeof(ValidateFilter));
  122. options.Filters.Add(typeof(CustomerExceptionFilterAttribute));
  123. options.Filters.Add(typeof(CustomerActionFilterAttribute));
  124. // options.Filters.ReplaceOne(x => (x as ServiceFilterAttribute)?.ServiceType?.Name == nameof(ExceptionFilterAttribute), new ServiceFilterAttribute(typeof(ABCExceptionFilterAttribute)));
  125. // options.Filters.ReplaceOne(x => (x as ServiceFilterAttribute)?.ServiceType?.Name == nameof(AbpExceptionFilter), new ServiceFilterAttribute(typeof(MyExceptionFilter)));
  126. });
  127. //context.Services.TryAddTransient<IAuthorizationMiddlewareResultHandler, AuthorizationMiddlewareResultHandler>();
  128. ///解除https限制
  129. context.Services.AddOpenIddict()
  130. .AddServer(option =>
  131. {
  132. option.UseAspNetCore().DisableTransportSecurityRequirement();
  133. });
  134. //虚拟目录
  135. context.Services.AddSingleton(new MyFileProvider(configuration["VirtualPath:RealPath"], configuration["VirtualPath:Alias"]));
  136. /*
  137. Configure<AbpAspNetCoreMvcOptions>(options =>
  138. {
  139. options.ConventionalControllers
  140. .Create(typeof(PeisApplicationModule).Assembly, opts =>
  141. {
  142. opts.RootPath = "api/app";
  143. opts.UrlControllerNameNormalizer = (controller) =>
  144. {
  145. return controller.ControllerName;
  146. };
  147. opts.UrlActionNameNormalizer = (action) =>
  148. {
  149. return action.Action.ActionName;
  150. };
  151. });
  152. });
  153. */
  154. }
  155. /// <summary>
  156. /// 全局转换日期格式
  157. /// </summary>
  158. private void ConfigureJsonOptions()
  159. {
  160. //context.Services.AddControllers().AddJsonOptions(options =>
  161. //{
  162. // options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
  163. // options.JsonSerializerOptions.PropertyNamingPolicy = null;
  164. //});
  165. Configure<JsonOptions>(x =>
  166. {
  167. x.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
  168. x.JsonSerializerOptions.PropertyNamingPolicy = null;
  169. x.JsonSerializerOptions.Converters.Add(new JsonTimeSpanConverter());
  170. });
  171. Configure<AbpJsonOptions>(x =>
  172. {
  173. x.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
  174. });
  175. }
  176. private void ConfigureAuthentication(ServiceConfigurationContext context)
  177. {
  178. context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
  179. }
  180. private void ConfigureBundles()
  181. {
  182. Configure<AbpBundlingOptions>(options =>
  183. {
  184. options.StyleBundles.Configure(
  185. LeptonXLiteThemeBundles.Styles.Global,
  186. bundle =>
  187. {
  188. bundle.AddFiles("/global-styles.css");
  189. }
  190. );
  191. });
  192. }
  193. private void ConfigureUrls(IConfiguration configuration)
  194. {
  195. Configure<AppUrlOptions>(options =>
  196. {
  197. options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
  198. options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));
  199. options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"];
  200. options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password";
  201. });
  202. }
  203. private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
  204. {
  205. var hostingEnvironment = context.Services.GetHostingEnvironment();
  206. if (hostingEnvironment.IsDevelopment())
  207. {
  208. Configure<AbpVirtualFileSystemOptions>(options =>
  209. {
  210. options.FileSets.ReplaceEmbeddedByPhysical<PeisDomainSharedModule>(
  211. Path.Combine(hostingEnvironment.ContentRootPath,
  212. $"..{Path.DirectorySeparatorChar}Shentun.Peis.Domain.Shared"));
  213. options.FileSets.ReplaceEmbeddedByPhysical<PeisDomainModule>(
  214. Path.Combine(hostingEnvironment.ContentRootPath,
  215. $"..{Path.DirectorySeparatorChar}Shentun.Peis.Domain"));
  216. options.FileSets.ReplaceEmbeddedByPhysical<PeisApplicationContractsModule>(
  217. Path.Combine(hostingEnvironment.ContentRootPath,
  218. $"..{Path.DirectorySeparatorChar}Shentun.Peis.Application.Contracts"));
  219. options.FileSets.ReplaceEmbeddedByPhysical<PeisApplicationModule>(
  220. Path.Combine(hostingEnvironment.ContentRootPath,
  221. $"..{Path.DirectorySeparatorChar}Shentun.Peis.Application"));
  222. });
  223. }
  224. }
  225. private void ConfigureConventionalControllers()
  226. {
  227. #region 配置隐藏api
  228. Configure<MvcOptions>(options =>
  229. {
  230. options.Conventions.Add(new ApplicationDescription());
  231. });
  232. #endregion
  233. Configure<AbpAspNetCoreMvcOptions>(options =>
  234. {
  235. options.ConventionalControllers.Create(typeof(PeisApplicationModule).Assembly);
  236. });
  237. }
  238. private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
  239. {
  240. context.Services.AddAbpSwaggerGenWithOAuth(
  241. configuration["AuthServer:Authority"],
  242. new Dictionary<string, string>
  243. {
  244. {"Peis", "Peis API"}
  245. },
  246. options =>
  247. {
  248. //options.SwaggerDoc("v1", new OpenApiInfo { Title = "Peis API", Version = "v1" });
  249. //options.DocInclusionPredicate((docName, description) => true);
  250. //options.CustomSchemaIds(type => type.FullName);
  251. options.SwaggerDoc("Work", new OpenApiInfo { Title = "业务API", Version = "V1", Description = "业务API" });
  252. options.SwaggerDoc("Sys", new OpenApiInfo { Title = "底层API", Version = "V1", Description = "底层API" });
  253. options.DocInclusionPredicate((docName, description) =>
  254. {
  255. if (!description.TryGetMethodInfo(out MethodInfo method))
  256. {
  257. return false;
  258. }
  259. /*使ApiExplorerSettingsAttribute里面的GroupName进行特性标识
  260. * DeclaringType只能获取controller上的特性
  261. * action的特性为主
  262. * */
  263. var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
  264. if (version.Any())
  265. {
  266. if (version.Any(v => v == docName))
  267. //选择了sys,并且分组不为User
  268. return true;
  269. }
  270. else
  271. {
  272. if (docName == "Sys")
  273. {
  274. return true;
  275. }
  276. }
  277. //这里获取action的特性
  278. var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
  279. if (actionVersion.Any())
  280. {
  281. return actionVersion.Any(v => v == docName);
  282. }
  283. return false;
  284. });
  285. });
  286. }
  287. private void ConfigureLocalization()
  288. {
  289. Configure<AbpLocalizationOptions>(options =>
  290. {
  291. options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
  292. options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
  293. options.Languages.Add(new LanguageInfo("en", "en", "English"));
  294. options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
  295. options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
  296. options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
  297. options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
  298. options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is"));
  299. options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
  300. options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
  301. options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
  302. options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
  303. options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
  304. options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
  305. options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
  306. options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
  307. options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
  308. options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
  309. options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
  310. options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά"));
  311. });
  312. }
  313. private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
  314. {
  315. context.Services.AddCors(options =>
  316. {
  317. options.AddDefaultPolicy(builder =>
  318. {
  319. builder
  320. .WithOrigins(
  321. configuration["App:CorsOrigins"]
  322. .Split(",", StringSplitOptions.RemoveEmptyEntries)
  323. .Select(o => o.RemovePostFix("/"))
  324. .ToArray()
  325. )
  326. .WithAbpExposedHeaders()
  327. .SetIsOriginAllowedToAllowWildcardSubdomains()
  328. .AllowAnyHeader()
  329. .AllowAnyMethod()
  330. .AllowCredentials();
  331. });
  332. });
  333. //添加swagger中文注释
  334. context.Services.AddSwaggerGen(options =>
  335. {
  336. //var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
  337. var baseDirectory = AppContext.BaseDirectory;
  338. //Serilog.Log.Information("swagger地址1:" + baseDirectory);
  339. //var baseDirectory2 = Path.GetDirectoryName(typeof(Program).Assembly.Location);
  340. //Serilog.Log.Information("swagger地址2:" + baseDirectory2);
  341. //var baseDirectory3 = AppDomain.CurrentDomain.BaseDirectory;
  342. //Serilog.Log.Information("swagger地址3:" + baseDirectory3);
  343. var commentsFile = Path.Combine(baseDirectory, "Shentun.Peis.Application.xml");
  344. options.IncludeXmlComments(commentsFile, true);
  345. var commentsFileDro = Path.Combine(baseDirectory, "Shentun.Peis.Application.Contracts.xml");
  346. options.IncludeXmlComments(commentsFileDro, true);
  347. var commentsFileapi = Path.Combine(baseDirectory, "Shentun.Peis.HttpApi.xml");
  348. options.IncludeXmlComments(commentsFileapi, true);
  349. });
  350. }
  351. public override void OnApplicationInitialization(ApplicationInitializationContext context)
  352. {
  353. var app = context.GetApplicationBuilder();
  354. var env = context.GetEnvironment();
  355. var configuration = context.GetConfiguration();
  356. //请求错误提示配置
  357. app.UseErrorHandling();
  358. if (env.IsDevelopment())
  359. {
  360. app.UseDeveloperExceptionPage();
  361. }
  362. app.UseAbpRequestLocalization();
  363. if (!env.IsDevelopment())
  364. {
  365. app.UseErrorPage();
  366. }
  367. app.UseCorrelationId();
  368. //var staticFile = new StaticFileOptions();
  369. //var filePath = env.ContentRootPath+"UpLoad\\";
  370. ////var filePath = env.ContentRootPath ;
  371. //staticFile.FileProvider = new PhysicalFileProvider(filePath);
  372. //app.UseStaticFiles(new StaticFileOptions
  373. //{
  374. // FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "UpLoad")),
  375. // RequestPath="/UpLoad"
  376. //});
  377. app.UseStaticFiles();
  378. app.UseStaticFiles(new StaticFileOptions
  379. {
  380. FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "ReportFile")),
  381. RequestPath = "/ReportFile"
  382. });
  383. app.UseStaticFiles(new StaticFileOptions
  384. {
  385. FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "UpLoad")),
  386. RequestPath = "/UpLoad"
  387. });
  388. //虚拟目录
  389. app.UseStaticFiles(new StaticFileOptions
  390. {
  391. FileProvider = new PhysicalFileProvider(configuration["VirtualPath:RealPath"]),
  392. RequestPath = configuration["VirtualPath:RequestPath"]
  393. });
  394. app.UseRouting();
  395. app.UseCors();
  396. app.UseAuthentication();
  397. app.UseAbpOpenIddictValidation();
  398. if (MultiTenancyConsts.IsEnabled)
  399. {
  400. app.UseMultiTenancy();
  401. }
  402. app.UseUnitOfWork();
  403. app.UseAuthorization();
  404. //app.UseMiddleware(typeof(AuthorizationMiddlewareResultHandler));
  405. app.UseSwagger();
  406. app.UseAbpSwaggerUI(c =>
  407. {
  408. //c.SwaggerEndpoint("/swagger/v1/swagger.json", "Peis API");
  409. c.SwaggerEndpoint($"/swagger/Work/swagger.json", "业务API"); //分组显示
  410. c.SwaggerEndpoint($"/swagger/Sys/swagger.json", "底层API"); //分组显示
  411. //c.RoutePrefix = string.Empty; // url 中不显示swagger
  412. var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
  413. c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
  414. c.OAuthScopes("Peis");
  415. c.DefaultModelExpandDepth(-1);
  416. });
  417. app.UseAuditing();
  418. app.UseAbpSerilogEnrichers();
  419. app.UseConfiguredEndpoints();
  420. }
  421. }