using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; 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.Tokens; using Microsoft.OpenApi.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Traffic.Repository.Infrastructures; using Traffic.Service.Filter; using Traffic.Service.Helpers; using Traffic.Service.Implements; using Traffic.Service.Interfaces; namespace Traffic.Api { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } 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.AddControllers(); services.AddSingleton(); services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddLogging(builder => { builder.AddConfiguration(Configuration.GetSection("Logging")) .AddFilter("Microsoft", LogLevel.Warning) .AddConsole() .AddDebug(); }); SetCors(services); SetSwagger(services); SetJwtBearer(services); } private static void SetCors(IServiceCollection services) { services.AddCors(o => o.AddPolicy("Traffic", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); })); } private static void SetJwtBearer(IServiceCollection services) { 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 = "Traffic", // 通常不太需要驗證 Audience ValidateAudience = false, //ValidAudience = "JwtAuthDemo", // 不驗證就不需要填寫 // 一般我們都會驗證 Token 的有效期間 ValidateLifetime = true, // 如果 Token 中包含 key 才需要驗證,一般都只有簽章而已 ValidateIssuerSigningKey = false, // "1234567890123456" 應該從 IConfiguration 取得 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("wgQWt6kNQR3dyYoCopq1")) }; }); } private static void SetSwagger(IServiceCollection services) { services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Traffic.Api", Version = "v1" }); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = $@"JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below. \r\n\r\n Example: 'Bearer 12345abcdef'", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); //Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header, }, new List() } }); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Traffic.Api v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseCors("Traffic"); app.UseAuthentication();//先驗證 app.UseAuthorization(); //再授權 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }