using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace CorsServer.WebApi31 { public class Startup { public Startup(IConfiguration configuration, IHostEnvironment hostingEnvironment, IWebHostEnvironment webHostEnvironment) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { //Config services.Configure(Configuration.GetSection(ApplicationConst.CorsConfigOptionName)); #region CORS AddCors_Config(services); //AddCors_Test(services); //AddCors_2(services); //AddCors_3(services); //AddCors_4(services); //AddCors_5(services); #endregion services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptionsSnapshot corsOtionsSnapshot) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //app.UseDatabaseErrorPage(); } else { //app.UseExceptionHandler("/Error"); //app.UseHsts(); } // app.UseHttpsRedirection(); #region 压缩和绑在静态文件 // app.UseResponseCompression(); // app.UseResponseCaching(); #endregion // app.UseStaticFiles(); // app.UseCookiePolicy(); // 根路径:全局访问前辍 http://www.custom.com/PathBase/ // app.UsePathBase("/api/"); app.UseRouting(); // app.UseRequestLocalization(); // UseRouting() 和 UseAuthentication()之间 // 中间件顺序 https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0#middleware-order app.UseCors(ApplicationConst.DefaultPolicyName); //app.UseAuthentication(); app.UseAuthorization(); //请在 Cookie策略中间件之后和 MVC中间件之前调用会话中间件。 // app.UseSession(); // app.UseResponseCompression(); // app.UseResponseCaching(); //自定义中间件 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } /// /// CORS 模板 /// private IServiceCollection AddCors_Template(IServiceCollection services) { services.AddCors(setup => { var corsOption = services.BuildServiceProvider().GetRequiredService>().Value; setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build //请求来源 //方法1:所有请求源 .AllowAnyOrigin() //方法2:lamda方法中自定义 //.SetIsOriginAllowed(requestOrigin => //{ // //请求源(请求的协议+主机+端口号,比如 http://wwwww.xxxx.com:80) // var address = requestOrigin; // //根据请求源自行过滤 // return true; //}) //方法3:WithOrigins方法参数自定义 //.WithOrigins(corsOption.Origins.ToArray()) //允许在WithOrigins方法中使用通配符(*等) //.SetIsOriginAllowedToAllowWildcardSubdomains() //请求方法(POST GET PUT DELETE OPTIONS等) .AllowAnyMethod() //.WithMethods(corsOption.Methods.ToArray()) //请求头 .AllowAnyHeader() //.WithHeaders(corsOption.Headers.ToArray()) //凭据 //.AllowCredentials() //.DisallowCredentials() //.WithExposedHeaders() //.SetPreflightMaxAge(TimeSpan.FromMinutes(10)) ; }); }); return services; } /// /// 全部设置项说明 /// private IServiceCollection AddCors_Info(IServiceCollection services) { services.AddCors(setup => { setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build //设置允许跨域的请求来源 .AllowAnyOrigin() //允许任何请求来源 //.SetIsOriginAllowed(_=> true) //使用Func 委托方法,自定义是否允许请求源跨域 //.WithOrigins() //允许指定请求来源 //.SetIsOriginAllowedToAllowWildcardSubdomains() //允许WithOrigins()方法,在请求源中使用通配符(*等) //设置允许跨域的HTTP方法(POST GET PUT DELETE OPTIONS等) .AllowAnyMethod() //允许所有方法 //.WithMethods() //允许指定方法 //设置允许跨域的请求标头 .AllowAnyHeader() //允许所有请求头 //.WithHeaders() //允许指定请求头 //跨域请求中的凭据 .AllowCredentials() //允许凭据:证书中包含缓存(cookies)和HTTP验证协议(HTTP authentication schemes) //.DisallowCredentials() //拒绝凭据 //设置公开的非简单响应标头 /设置暴露的自定义响应头(默认情况下,浏览器只会暴露默认的响应头给应用,其它自定义影响头不会暴露给应用程序) .WithExposedHeaders("x-custom-a", "x-custom-b") //设置预检过期时间 .SetPreflightMaxAge(TimeSpan.FromMinutes(10)) //此标头指定可缓存对预检请求的响应的时间长度 ; /*特别说明: 出于安全考虑:.net core 2.1开始, AllowAnyOrigin() 和 AllowCredentials() 不能同时使用 解决方案: 1、使用AllowCredentials()时,用.SetIsOriginAllowed(_ => true) 代替 AllowAnyOrigin() 2、使用AllowCredentials()时,用 WithOrigins()指定请求来源(使用SetIsOriginAllowedToAllowWildcardSubdomains()来启用通配符) 代替 AllowAnyOrigin() 3、自定义中间件 */ }); }); return services; } #region 注册不同的Cors策略 /// /// 测试 /// private IServiceCollection AddCors_Test(IServiceCollection services) { services.AddCors(setup => { setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build //请求来源 //.AllowAnyOrigin() //.WithOrigins() .SetIsOriginAllowed(requestOrigin => { var cc = requestOrigin; return true; }) //.SetIsOriginAllowedToAllowWildcardSubdomains() //请求方法(POST GET PUT DELETE OPTIONS等) .AllowAnyMethod() //.WithMethods() //请求头 .AllowAnyHeader() //.WithHeaders() //凭据 //.AllowCredentials() //.DisallowCredentials() //.WithExposedHeaders() ; }); }); return services; } private IServiceCollection AddCors_Single(IServiceCollection services) { services.AddCors(setup => { setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build //请求来源 .AllowAnyOrigin() //.WithOrigins() //.SetIsOriginAllowed(_ => true) //.SetIsOriginAllowedToAllowWildcardSubdomains() //请求方法(POST GET PUT DELETE OPTIONS等) //.AllowAnyMethod() //.WithMethods() //请求头 //.AllowAnyHeader() //.WithHeaders() //凭据 //.AllowCredentials() //.DisallowCredentials() //.WithExposedHeaders() ; }); }); return services; } private IServiceCollection AddCors_All(IServiceCollection services) { services.AddCors(setup => { setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() ; }); }); return services; } private IServiceCollection AddCors_3(IServiceCollection services) { services.AddCors(setup => { var corsOption = services.BuildServiceProvider().GetRequiredService>().Value; setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build .WithOrigins(corsOption.Origins.ToArray()) .WithMethods(corsOption.Methods.ToArray()) .WithHeaders(corsOption.Headers.ToArray()) .WithExposedHeaders(corsOption.ExposedHeaders.ToArray()); }); }); return services; } private IServiceCollection AddCors_4(IServiceCollection services) { services.AddCors(setup => { setup.AddPolicy(ApplicationConst.DefaultPolicyName, build => { build.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("x-custom-error"); }); }); return services; } private IServiceCollection AddCors_5(IServiceCollection services) { services.AddCors(setup => { var corsOption = services.BuildServiceProvider().GetRequiredService>().Value; setup.AddPolicy(ApplicationConst.DefaultPolicyName, builder => { builder ////.SetIsOriginAllowedToAllowWildcardSubdomains() .WithOrigins("http://localhost:5002") //.AllowAnyMethod() ////.WithMethods(corsOption.Methods.ToArray()) //.AllowAnyHeader() ////.WithHeaders(corsOption.Headers.ToArray()) ////.WithExposedHeaders(corsOption.ExposedHeaders.ToArray()) ; }); }); return services; } private IServiceCollection AddCors_Config(IServiceCollection services) { services.AddCors(setup => { var corsOption = services.BuildServiceProvider().GetRequiredService>().Value; setup.AddPolicy(ApplicationConst.DefaultPolicyName, builder => { if (corsOption.Origins == null) { builder.SetIsOriginAllowed(_ => true); } else if (corsOption.Origins.Count == 0) { builder.SetIsOriginAllowed(_ => true); } else if (corsOption.Origins.Contains("*")) { builder.SetIsOriginAllowed(_ => true); } else { builder.WithOrigins(corsOption.Origins.ToArray()); builder.SetIsOriginAllowedToAllowWildcardSubdomains(); } if (corsOption.Methods == null || corsOption.Methods.Count == 0) { builder.AllowAnyMethod(); } else if (corsOption.Methods.Contains("*")) { builder.AllowAnyMethod(); } else { builder.WithMethods(corsOption.Methods.ToArray()); } if (corsOption.Headers == null || corsOption.Headers.Count == 0) { builder.AllowAnyHeader(); } else if (corsOption.Headers.Contains("*")) { builder.AllowAnyHeader(); } else { builder.WithMethods(corsOption.Headers.ToArray()); } if (corsOption.ExposedHeaders != null && corsOption.ExposedHeaders.Count > 0) { builder.WithExposedHeaders(corsOption.ExposedHeaders.ToArray()); } if (corsOption.AllowCredentials) { builder.AllowCredentials(); } else { builder.DisallowCredentials(); } if (corsOption.PreflightMaxAge.TotalSeconds > 0) { builder.SetPreflightMaxAge(corsOption.PreflightMaxAge); } }); }); return services; } #endregion } }