0
0

Startup.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Collections.Generic;
  7. using Microsoft.AspNetCore.Http;
  8. using Microsoft.AspNetCore.Builder;
  9. using Microsoft.AspNetCore.Hosting;
  10. using Microsoft.AspNetCore.Authentication;
  11. using Microsoft.AspNetCore.Authentication.JwtBearer;
  12. using Microsoft.OpenApi.Models;
  13. using Microsoft.IdentityModel.Tokens;
  14. using Microsoft.Extensions.Hosting;
  15. using Microsoft.Extensions.DependencyInjection;
  16. using Microsoft.Extensions.DependencyInjection.Extensions;
  17. using Newtonsoft.Json;
  18. using Newtonsoft.Json.Serialization;
  19. using Autofac;
  20. using Autofac.Extras.DynamicProxy;
  21. using AutoMapper;
  22. //using FluentValidation;
  23. //using FluentValidation.AspNetCore;
  24. using Admin.Core.Common.Helpers;
  25. using Admin.Core.Common.Configs;
  26. using Admin.Core.Common.Auth;
  27. using Admin.Core.Auth;
  28. using Admin.Core.Enums;
  29. using Admin.Core.Filters;
  30. using Admin.Core.Db;
  31. using Admin.Core.Common.Cache;
  32. using Admin.Core.Aop;
  33. using Admin.Core.Logs;
  34. using PermissionHandler = Admin.Core.Auth.PermissionHandler;
  35. using Admin.Core.Extensions;
  36. using Admin.Core.Common.Attributes;
  37. namespace Admin.Core
  38. {
  39. public class Startup
  40. {
  41. private readonly IHostEnvironment _env;
  42. private static string basePath => AppContext.BaseDirectory;
  43. private readonly AppConfig _appConfig;
  44. public Startup(IWebHostEnvironment env)
  45. {
  46. _env = env;
  47. _appConfig = new ConfigHelper().Get<AppConfig>("appconfig", env.EnvironmentName) ?? new AppConfig();
  48. }
  49. public void ConfigureServices(IServiceCollection services)
  50. {
  51. //应用配置
  52. services.AddSingleton(_appConfig);
  53. //上传配置
  54. var uploadConfig = new ConfigHelper().Load("uploadconfig", _env.EnvironmentName, true);
  55. services.Configure<UploadConfig>(uploadConfig);
  56. #region AutoMapper 自动映射
  57. var serviceAssembly = Assembly.Load("Admin.Core.Service");
  58. services.AddAutoMapper(serviceAssembly);
  59. #endregion
  60. #region Cors 跨域
  61. services.AddCors(c =>
  62. {
  63. c.AddPolicy("Limit", policy =>
  64. {
  65. policy
  66. .WithOrigins(_appConfig.Urls)
  67. .AllowAnyHeader()
  68. .AllowAnyMethod();
  69. });
  70. });
  71. #endregion
  72. #region Swagger Api文档
  73. if (_env.IsDevelopment() || _appConfig.Swagger)
  74. {
  75. services.AddSwaggerGen(c =>
  76. {
  77. typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
  78. {
  79. c.SwaggerDoc(version, new OpenApiInfo
  80. {
  81. Version = version,
  82. Title = "Admin.Core"
  83. });
  84. //c.OrderActionsBy(o => o.RelativePath);
  85. });
  86. var xmlPath = Path.Combine(basePath, "Admin.Core.xml");
  87. c.IncludeXmlComments(xmlPath, true);
  88. var xmlCommonPath = Path.Combine(basePath, "Admin.Core.Common.xml");
  89. c.IncludeXmlComments(xmlCommonPath, true);
  90. var xmlModelPath = Path.Combine(basePath, "Admin.Core.Model.xml");
  91. c.IncludeXmlComments(xmlModelPath);
  92. var xmlServicesPath = Path.Combine(basePath, "Admin.Core.Service.xml");
  93. c.IncludeXmlComments(xmlServicesPath);
  94. //添加设置Token的按钮
  95. c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
  96. {
  97. Description = "Value: Bearer {token}",
  98. Name = "Authorization",
  99. In = ParameterLocation.Header,
  100. Type = SecuritySchemeType.ApiKey,
  101. Scheme = "Bearer"
  102. });
  103. //添加Jwt验证设置
  104. c.AddSecurityRequirement(new OpenApiSecurityRequirement()
  105. {
  106. {
  107. new OpenApiSecurityScheme
  108. {
  109. Reference = new OpenApiReference
  110. {
  111. Type = ReferenceType.SecurityScheme,
  112. Id = "Bearer"
  113. },
  114. Scheme = "oauth2",
  115. Name = "Bearer",
  116. In = ParameterLocation.Header,
  117. },
  118. new List<string>()
  119. }
  120. });
  121. });
  122. }
  123. #endregion
  124. #region Jwt身份认证
  125. var jwtConfig = new ConfigHelper().Get<JwtConfig>("jwtconfig", _env.EnvironmentName);
  126. services.TryAddSingleton(jwtConfig);
  127. services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  128. services.TryAddSingleton<IUser, User>();
  129. services.TryAddSingleton<IUserToken, UserToken>();
  130. services.AddScoped<IPermissionHandler, PermissionHandler>();
  131. services.AddAuthentication(options =>
  132. {
  133. options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
  134. options.DefaultChallengeScheme = nameof(ResponseAuthenticationHandler); //401
  135. options.DefaultForbidScheme = nameof(ResponseAuthenticationHandler); //403
  136. })
  137. .AddJwtBearer(options =>
  138. {
  139. options.TokenValidationParameters = new TokenValidationParameters
  140. {
  141. ValidateIssuer = true,
  142. ValidateAudience = true,
  143. ValidateLifetime = true,
  144. ValidateIssuerSigningKey = true,
  145. ValidIssuer = jwtConfig.Issuer,
  146. ValidAudience = jwtConfig.Audience,
  147. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey)),
  148. ClockSkew = TimeSpan.Zero
  149. };
  150. })
  151. .AddScheme<AuthenticationSchemeOptions, ResponseAuthenticationHandler>(nameof(ResponseAuthenticationHandler), o => { }); ;
  152. #endregion
  153. #region 控制器
  154. if (_appConfig.Log.Operation)
  155. {
  156. services.AddSingleton<ILogHandler, LogHandler>();
  157. }
  158. services.AddControllers(options =>
  159. {
  160. options.Filters.Add<AdminExceptionFilter>();
  161. if (_appConfig.Log.Operation)
  162. {
  163. options.Filters.Add<LogActionFilter>();
  164. }
  165. })
  166. //.AddFluentValidation(config =>
  167. //{
  168. // var assembly = Assembly.LoadFrom(Path.Combine(basePath, "Admin.Core.dll"));
  169. // config.RegisterValidatorsFromAssembly(assembly);
  170. //})
  171. .AddNewtonsoftJson(options =>
  172. {
  173. //忽略循环引用
  174. options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  175. //使用驼峰 首字母小写
  176. options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
  177. //设置时间格式
  178. options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
  179. });
  180. #endregion
  181. //数据库
  182. services.AddDb(_env,_appConfig);
  183. #region 缓存
  184. var cacheConfig = new ConfigHelper().Get<CacheConfig>("cacheconfig", _env.EnvironmentName);
  185. if (cacheConfig.Type == CacheType.Redis)
  186. {
  187. var csredis = new CSRedis.CSRedisClient(cacheConfig.Redis.ConnectionString);
  188. RedisHelper.Initialization(csredis);
  189. services.AddSingleton<ICache, RedisCache>();
  190. }
  191. else
  192. {
  193. services.AddMemoryCache();
  194. services.AddSingleton<ICache, MemoryCache>();
  195. }
  196. #endregion
  197. //阻止NLog接收状态消息
  198. services.Configure<ConsoleLifetimeOptions>(opts => opts.SuppressStatusMessages = true);
  199. }
  200. public void ConfigureContainer(ContainerBuilder builder)
  201. {
  202. #region AutoFac IOC容器
  203. try
  204. {
  205. #region Aop
  206. var interceptorServiceTypes = new List<Type>();
  207. if (_appConfig.Aop.Transaction)
  208. {
  209. builder.RegisterType<TransactionInterceptor>();
  210. interceptorServiceTypes.Add(typeof(TransactionInterceptor));
  211. }
  212. #endregion
  213. #region Service
  214. var assemblyServices = Assembly.Load("Admin.Core.Service");
  215. builder.RegisterAssemblyTypes(assemblyServices)
  216. .AsImplementedInterfaces()
  217. .InstancePerDependency()
  218. .EnableInterfaceInterceptors()
  219. .InterceptedBy(interceptorServiceTypes.ToArray());
  220. #endregion
  221. #region Repository
  222. var assemblyRepository = Assembly.Load("Admin.Core.Repository");
  223. builder.RegisterAssemblyTypes(assemblyRepository)
  224. .AsImplementedInterfaces()
  225. .InstancePerDependency();
  226. #endregion
  227. #region SingleInstance
  228. var assemblyCore = Assembly.Load("Admin.Core");
  229. var assemblyCommon = Assembly.Load("Admin.Core.Common");
  230. builder.RegisterAssemblyTypes(assemblyCore, assemblyCommon)
  231. .Where(t => t.GetCustomAttribute<SingleInstanceAttribute>() != null)
  232. .SingleInstance();
  233. #endregion
  234. }
  235. catch (Exception ex)
  236. {
  237. throw new Exception(ex.Message + "\n" + ex.InnerException);
  238. }
  239. #endregion
  240. }
  241. public void Configure(IApplicationBuilder app)
  242. {
  243. //启动事件
  244. //, IHostApplicationLifetime lifetime
  245. //lifetime.ApplicationStarted.Register(() =>
  246. //{
  247. // Console.WriteLine($"{_appConfig.Urls}\r\n");
  248. //});
  249. #region app配置
  250. //异常
  251. app.UseExceptionHandler("/Error");
  252. //静态文件
  253. app.UseUploadConfig();
  254. //路由
  255. app.UseRouting();
  256. //跨域
  257. app.UseCors("Limit");
  258. //认证
  259. app.UseAuthentication();
  260. //授权
  261. app.UseAuthorization();
  262. //配置端点
  263. app.UseEndpoints(endpoints =>
  264. {
  265. endpoints.MapControllers();
  266. });
  267. #endregion
  268. #region Swagger Api文档
  269. if (_env.IsDevelopment() || _appConfig.Swagger)
  270. {
  271. app.UseSwagger();
  272. app.UseSwaggerUI(c =>
  273. {
  274. typeof(ApiVersion).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
  275. {
  276. c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"Admin.Core {version}");
  277. });
  278. c.RoutePrefix = "";//直接根目录访问
  279. c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);//折叠Api
  280. c.DefaultModelsExpandDepth(-1);//不显示Models
  281. });
  282. }
  283. #endregion
  284. }
  285. }
  286. }