StartupExtensions.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System.IdentityModel.Tokens.Jwt;
  2. using System.Reflection;
  3. using Exceptionless;
  4. using FluentValidation;
  5. using FluentValidation.AspNetCore;
  6. using Hotline.Api.Filters;
  7. using Hotline.Api.Realtimes;
  8. using Hotline.Application;
  9. using Hotline.Application.Contracts;
  10. using Hotline.Application.Contracts.Configurations;
  11. using Hotline.CacheManager;
  12. using Hotline.CallCenter.Devices;
  13. using Hotline.NewRock;
  14. using Hotline.Permissions;
  15. using Hotline.Repository.SqlSugar;
  16. using Hotline.Settings;
  17. using Identity.Admin.HttpClient;
  18. using Mapster;
  19. using MapsterMapper;
  20. using MediatR;
  21. using Microsoft.AspNetCore.Authentication.JwtBearer;
  22. using Microsoft.AspNetCore.Authorization;
  23. using Microsoft.IdentityModel.Tokens;
  24. using Microsoft.OpenApi.Models;
  25. using Serilog;
  26. using XF.Domain.Dependency;
  27. namespace Hotline.Api;
  28. internal static class StartupExtensions
  29. {
  30. const string CorsOrigins = "CorsOrigins";
  31. internal static WebApplication ConfigureServices(this WebApplicationBuilder builder)
  32. {
  33. var services = builder.Services;
  34. var configuration = builder.Configuration;
  35. services.AddHttpContextAccessor();
  36. #if DEBUG
  37. builder.WebHost.UseUrls("http://192.168.100.36:50110", "http://localhost:50110");
  38. #endif
  39. services.Configure<DeviceConfigs>(d => configuration.GetSection(nameof(DeviceConfigs)).Bind(d));
  40. services.Configure<WorkTimeSettings>(d => configuration.GetSection(nameof(WorkTimeSettings)).Bind(d));
  41. // Add services to the container.
  42. services
  43. .BatchInjectServices()
  44. .AddApplication()
  45. ;
  46. var identityConfigs = configuration.GetSection(nameof(IdentityConfigs)).Get<IdentityConfigs>();
  47. services.AddIdentityClient(
  48. d =>
  49. {
  50. d.IdentityAddress = identityConfigs.IdentityUrl;
  51. d.IdentityApiAddress = identityConfigs.IdentityApiUrl;
  52. },
  53. //new IdentityClientConfiguration(identityConfigs.IdentityUrl, identityConfigs.IdentityApiUrl),
  54. d =>
  55. {
  56. d.ClientId = identityConfigs.ClientId;
  57. d.ClientSecret = identityConfigs.ClientSecret;
  58. d.ClientScope = identityConfigs.ClientScope;
  59. });
  60. JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
  61. services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  62. .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, d =>
  63. {
  64. d.Authority = identityConfigs.IdentityUrl;
  65. d.RequireHttpsMetadata = false;
  66. d.TokenValidationParameters = new TokenValidationParameters
  67. {
  68. ValidateAudience = false
  69. };
  70. //d.Audience = "hotline_api";
  71. d.Events = new JwtBearerEvents
  72. {
  73. OnMessageReceived = context =>
  74. {
  75. var accessToken = context.Request.Query["access_token"];
  76. // If the request is for our hub...
  77. var path = context.HttpContext.Request.Path;
  78. if (!string.IsNullOrEmpty(accessToken) &&
  79. (path.StartsWithSegments("/hubs/callcenter")))
  80. {
  81. // Read the token out of the query string
  82. context.Token = accessToken;
  83. }
  84. return Task.CompletedTask;
  85. }
  86. };
  87. })
  88. ;
  89. services.AddControllers(options =>
  90. {
  91. options.Filters.Add<UnifyResponseFilter>();
  92. options.Filters.Add<UserFriendlyExceptionFilter>();
  93. });
  94. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
  95. services.AddEndpointsApiExplorer();
  96. services.AddSwaggerGen(c =>
  97. {
  98. //添加文档
  99. c.SwaggerDoc("v1", new OpenApiInfo() { Title = "Hotline Api", Version = "v1.0", Description = "城市热线api" });
  100. //使用反射获取xml文件,并构造出文件的路径
  101. var xmlFile = "document.xml";
  102. //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
  103. var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
  104. // 启用xml注释. 该方法第二个参数启用控制器的注释,默认为false.
  105. c.IncludeXmlComments(xmlPath, true);
  106. var scheme = new OpenApiSecurityScheme()
  107. {
  108. Description = "Authorization header. \r\nExample: 'Bearer ***'",
  109. Reference = new OpenApiReference
  110. {
  111. Type = ReferenceType.SecurityScheme,
  112. Id = "Authorization"
  113. },
  114. Scheme = "oauth2",
  115. Name = "Authorization",
  116. In = ParameterLocation.Header,
  117. Type = SecuritySchemeType.ApiKey,
  118. };
  119. c.AddSecurityDefinition("Authorization", scheme);
  120. var requirement = new OpenApiSecurityRequirement();
  121. requirement[scheme] = new List<string>();
  122. c.AddSecurityRequirement(requirement);
  123. });
  124. //signalR
  125. builder.Services.AddSignalR().AddStackExchangeRedis(configuration.GetConnectionString("Redis"), options =>
  126. {
  127. options.Configuration.ChannelPrefix = "callcenter:signalR:";
  128. });
  129. /* CORS */
  130. services.AddCors(options =>
  131. {
  132. options.AddPolicy(name: CorsOrigins,
  133. builder =>
  134. {
  135. var origins = configuration.GetSection("Cors:Origins").Get<string[]>();
  136. builder.SetIsOriginAllowed(a =>
  137. {
  138. return origins.Any(origin => origin.StartsWith("*.", StringComparison.Ordinal)
  139. ? a.EndsWith(origin[1..], StringComparison.Ordinal)
  140. : a.Equals(origin, StringComparison.Ordinal));
  141. })
  142. .AllowAnyHeader()
  143. .AllowAnyMethod()
  144. .AllowCredentials();
  145. });
  146. });
  147. //mapster
  148. var config = TypeAdapterConfig.GlobalSettings;
  149. services.AddSingleton(config);
  150. services.AddScoped<IMapper, ServiceMapper>();
  151. //mediatr
  152. services.AddMediatR(Assembly.GetExecutingAssembly(), typeof(ApplicationStartupExtensions).Assembly);
  153. //迅时IPPBX
  154. var deviceConfigs = configuration.GetSection("DeviceConfigs").Get<DeviceConfigs>();
  155. services.AddNewRock(deviceConfigs.Address);
  156. //sqlsugar
  157. services.AddSqlSugar(configuration, "Hotline");
  158. //cache
  159. services.AddCache(d =>
  160. {
  161. d.ConnectionString = configuration.GetConnectionString("Redis");
  162. d.Prefix = "Hotline";
  163. });
  164. //validator
  165. services.AddFluentValidationAutoValidation(config =>
  166. {
  167. config.DisableDataAnnotationsValidation = true;
  168. })
  169. .AddValidatorsFromAssembly(typeof(AppContractsStartupExtensions).Assembly);
  170. //ex log
  171. services.AddExceptionless(configuration);
  172. services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
  173. services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
  174. return builder.Build();
  175. }
  176. internal static WebApplication ConfigurePipelines(this WebApplication app)
  177. {
  178. app.UseSerilogRequestLogging();
  179. var useExless = app.Configuration.GetSection("Exceptionless:InUse").Get<bool>();
  180. if (useExless)
  181. {
  182. app.UseExceptionless();
  183. }
  184. var swaggerEnable = app.Configuration.GetSection("Swagger").Get<bool>();
  185. // Configure the HTTP request pipeline.
  186. if (swaggerEnable)
  187. {
  188. app.UseSwagger();
  189. app.UseSwaggerUI();
  190. }
  191. app.UseCors(CorsOrigins);
  192. app.UseAuthentication();
  193. app.UseAuthorization();
  194. app.MapHub<CallCenterHub>("/hubs/callcenter");
  195. //app.UseMiddleware<TempTokenMiddleware>();
  196. app.MapControllers()
  197. .RequireAuthorization();
  198. return app;
  199. }
  200. }