using FrontendWebApi.Jwt; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; 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 Repository.Services.Implement; using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Text; using System.Threading.Tasks; using static FrontendWebApi.Jwt.JwtHelpers; namespace FrontendWebApi { public class Startup { public DBConfig dBConfig = new DBConfig() { MSSqlDBConfig = new MSSqlDBConfig(), MySqlDBConfig = new MySqlDBConfig() }; public Startup(IConfiguration configuration) { Configuration = configuration; 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"); 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"); } 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.AddSingleton(); services.AddControllersWithViews(); //services.AddControllers(); services.AddCors(options => { options.AddPolicy("CorsPolicy", policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .WithExposedHeaders("Content-Disposition"); }); }); 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 注入 services.Configure(Configuration.GetSection("ObixApiConfig")); #region Repository 注入 services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); #endregion Repository 注入 #region JWT 注入 services.AddTransient(); //services.AddSingleton(); 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 注入 double loginExpireMinute = this.Configuration.GetValue("LoginExpireMinute"); services.AddSession(options => { options.Cookie.Name = "WebApi.Session"; 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(); //IdentityModelEventSource.ShowPII = true; app.UseRouting(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); app.UseCors(x => x .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowed(origin => true) // allow any origin .AllowCredentials()); app.UseAuthentication(); app.UseAuthorization(); app.Use(async (context, next) => { context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); await next(); }); //app.UseEndpoints(endpoints => //{ // endpoints.MapControllers(); //}); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Login}/{action=Index}/{id?}"); }); } } }