using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Repository.Helper; using Repository.BackendRepository.Implement; using Repository.BackendRepository.Interface; using Repository.BaseRepository.Implement; using Repository.BaseRepository.Interface; using Repository.FrontendRepository.Implement; using Repository.FrontendRepository.Interface; using Repository.Models; using System; using System.Linq; using Backend.Jwt; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; using System.IdentityModel.Tokens.Jwt; using Microsoft.AspNetCore.Http; using Backend.Quartz.Jobs; using Backend.Quartz; using Quartz.Impl; using Quartz.Spi; using Quartz; namespace Backend { public class Startup { public DBConfig dBConfig = new DBConfig() { MSSqlDBConfig = new MSSqlDBConfig(), MySqlDBConfig = new MySqlDBConfig() }; public BackEndConfig BackEndConfig = new BackEndConfig() { NiagaraDataSyncConfig=new NiagaraDataSyncConfig() }; public Startup(IConfiguration configuration) { Configuration = configuration; #region MSSql DB Config //dBConfig.MSSqlDBConfig.Server = Configuration.GetValue("DBConfig:MSSqlDBConfig:Server"); //dBConfig.MSSqlDBConfig.Port = Configuration.GetValue("DBConfig:MSSqlDBConfig:Port"); //dBConfig.MSSqlDBConfig.Root = Configuration.GetValue("DBConfig:MSSqlDBConfig:Root"); //dBConfig.MSSqlDBConfig.Password = Configuration.GetValue("DBConfig:MSSqlDBConfig:Password"); //dBConfig.MSSqlDBConfig.Database = Configuration.GetValue("DBConfig:MSSqlDBConfig:Database"); #endregion MSSql DB Config #region MySql DB Config dBConfig.MySqlDBConfig.Server = Configuration.GetValue("DBConfig:MySqlDBConfig:Server"); dBConfig.MySqlDBConfig.Port = Configuration.GetValue("DBConfig:MySqlDBConfig:Port"); dBConfig.MySqlDBConfig.Root = Configuration.GetValue("DBConfig:MySqlDBConfig:Root"); dBConfig.MySqlDBConfig.Password = Configuration.GetValue("DBConfig:MySqlDBConfig:Password"); dBConfig.MySqlDBConfig.Database = Configuration.GetValue("DBConfig:MySqlDBConfig:Database"); #endregion MySql DB Config #region NiagaraDataSync Config BackEndConfig.NiagaraDataSyncConfig.UrlSlot = Configuration.GetValue("BackEndConfig:NiagaraDataSyncConfig:UrlSlot"); BackEndConfig.NiagaraDataSyncConfig.ObixQuery= Configuration.GetValue("BackEndConfig:NiagaraDataSyncConfig:ObixQuery"); BackEndConfig.NiagaraDataSyncConfig.ObixHisBqlQuery = Configuration.GetValue("BackEndConfig:NiagaraDataSyncConfig:ObixHisBqlQuery"); BackEndConfig.NiagaraDataSyncConfig.ObixHisUrlQuery = Configuration.GetValue("BackEndConfig:NiagaraDataSyncConfig:ObixHisUrlQuery"); #endregion } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddCors(options => { options.AddPolicy("CorsPolicy", policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); services.AddLogging( builder => { builder.AddFilter("Microsoft", LogLevel.Warning) .AddFilter("System", LogLevel.Warning) .AddFilter("NToastNotify", LogLevel.Warning) .AddConsole(); }); #region DBHelper 注入 services.Configure(Configuration.GetSection("DBConfig")); services.AddTransient(); #endregion DBHelper 注入 #region BackEndConfigHelper 注入 services.Configure(Configuration.GetSection("BackEndConfig")); services.AddTransient(); #endregion DBHelper 注入 #region Repository 注入 services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); #endregion Repository 注入 #region 添加Quartz服務 services.AddTransient(); services.AddTransient(); services.AddHostedService(); #endregion #region JWT 注入 services.AddTransient(); services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // 當驗證失敗時,回應標頭會包含 WWW-Authenticate 標頭,這裡會顯示失敗的詳細錯誤原因 options.IncludeErrorDetails = true; // 預設值為 true,有時會特別關閉 options.TokenValidationParameters = new TokenValidationParameters() { // 透過這項宣告,就可以從 "sub" 取值並設定給 User.Identity.Name NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", // 透過這項宣告,就可以從 "roles" 取值,並可讓 [Authorize] 判斷角色 RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", // 一般我們都會驗證 Issuer ValidateIssuer = true, ValidIssuer = Configuration.GetValue("JwtSettings:Issuer"), RequireExpirationTime = true, // 通常不太需要驗證 Audience ValidateAudience = false, //ValidAudience = "JwtAuthDemo", // 不驗證就不需要填寫 // 一般我們都會驗證 Token 的有效期間 ValidateLifetime = true, // 如果 Token 中包含 key 才需要驗證,一般都只有簽章而已 ValidateIssuerSigningKey = false, // "1234567890123456" 應該從 IConfiguration 取得 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue("JwtSettings:SignKey"))) }; }); #endregion JWT 注入 #region 電錶歸檔(設定每 天 執行一次) services.AddSingleton(); services.AddSingleton( new JobSchedule(jobType: typeof(ArchiveElectricMeterDayJob), cronExpression: Configuration.GetValue("BackgroundServiceCron:ArchiveElectricMeterDayJob")) ); #endregion //#region 定時取得氣象API //services.AddSingleton(); //services.AddSingleton( //new JobSchedule(jobType: typeof(WeatherAPIJob), cronExpression: Configuration.GetValue("BackgroundServiceCron:WeatherAPIJob")) //); //#endregion double loginExpireMinute = this.Configuration.GetValue("LoginExpireMinute"); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(loginExpireMinute); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddFile("Logs/log-{Date}.txt"); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseSession(); app.UseHttpsRedirection(); app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => { ctx.Context.Response.Headers.Append("Access-Control-Allow-Origin", "*"); } }); app.UseRouting(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); app.UseCors(x => x .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowed(origin => true) // allow any origin .AllowCredentials()); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Login}/{action=Index}/{id?}"); }); } } }