在 asp net core web api v3.0 中启用 CORS 的问题

Posted

技术标签:

【中文标题】在 asp net core web api v3.0 中启用 CORS 的问题【英文标题】:Problem in enabling CORS in asp net core web api v3.0 【发布时间】:2020-03-23 03:26:19 【问题描述】:

我在我的 Web API 项目中使用 asp net core 3.0。我创建了各种 API,都可以通过 Swagger 或 Postman 访问。但是,当尝试通过任何其他客户端(如 React)访问相同的内容时,会收到不允许的方法(405 错误代码)。在进一步投资时,我发现一开始,从 React 应用程序收到 OPTION 请求,而 net core web API 应用程序给出了 405 状态码。此外,我发现我需要启用所有方法以及来自网络核心应用程序的来源以接受所有类型的请求,否则它将不接受 OPTION 请求。为此,我在 startup.cs 文件中启用了 CORS 策略,但仍然没有运气。以下是我的 startup.cs 文件:

public class Startup

    public Startup(IConfiguration configuration)
    

        Configuration = configuration;

        var elasticUri = Configuration["ElasticConfiguration:Uri"];

        Log.Logger = new LoggerConfiguration()
            .Enrich.FromLogContext()
            .Enrich.WithExceptionDetails()
            .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elasticUri))
            
                MinimumLogEventLevel = LogEventLevel.Verbose,
                AutoRegisterTemplate = true,
            )
        .CreateLogger();


    

    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.Configure<IISServerOptions>(options =>
        
            options.AutomaticAuthentication = false;
        );
        services.Configure<ApiBehaviorOptions>(options =>
        
            //To handle ModelState Errors manually as ApiController attribute handles those automatically
            //and return its own response.
            options.SuppressModelStateInvalidFilter = true;
        );

       services.AddCors(options =>
        
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());
        );

        services.AddControllers(options =>
        
            //To accept browser headers.
            options.RespectBrowserAcceptHeader = true;
        ).
         AddNewtonsoftJson(options =>
         
             // Use the default property (Pascal) casing
             options.SerializerSettings.ContractResolver = new DefaultContractResolver();
             options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

         ).
        AddJsonOptions(options =>
         
             //Not applying any property naming policy
             options.JsonSerializerOptions.PropertyNamingPolicy = null;
             options.JsonSerializerOptions.IgnoreNullValues = true;

         ).
        AddXmlSerializerFormatters().
        AddXmlDataContractSerializerFormatters();
    

    // 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)
    
        app.UseCors("CorsPolicy");

        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
              

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (html, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        );

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllers();
        );

        //Configuring serilog
        loggerFactory.AddSerilog();

    

我尝试使用 POSTMAN 的 OPTIONS 方法测试相同的 API。它还将 Http 状态代码设为 405。但是当尝试使用 POST 方法访问相同的请求时,我成功收到了响应。

上面的代码有什么问题,或者是Configure()中调用中间件的顺序有问题吗?

【问题讨论】:

【参考方案1】:

您需要在您的 web api 项目下的 Startup.cs 文件中添加 Cors

    Startup.cs 中添加此变量

只读字符串 MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    在文件 Startup.cs 的方法 ConfigureServices 中的 services.AddControllers() 之前添加 services.AddCors
services.AddCors(options =>

    options.AddPolicy(MyAllowSpecificOrigins,
    builder =>
    
       builder.WithOrigins("http://localhost:4000",
       "http://www.yourdomain.com")
       .AllowAnyHeader()
       .AllowAnyMethod();
    );
);

services.AddControllers();

*** 您可以只传递 * 来允许所有,而不是在 WithOrigins 方法中传递 http://localhost:4000","http://www.yourdomain.com

    在 Startup.cs 文件中的方法 Configure 中的 app.UseAuthentication() 之前添加 app.UseCors

app.UseCors(MyAllowSpecificOrigins);

Check this Microsoft help

【讨论】:

【参考方案2】:

尝试添加扩展方法并修改你的启动类:

扩展方法:

public static void AddApplicationError(this HttpResponse response, string 
    message)

    response.Headers.Add("Application-Error", message);
    response.Headers.Add("Access-Control-Expose-Headers", "Application-Error");
    response.Headers.Add("Access-Control-Allow-Origin", "*");

Startup.cs:

        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        
        else
        
            app.UseExceptionHandler(builder =>
            
                builder.Run(async context =>
                
                    context.Response.StatusCode = (int) 
                 HttpStatusCode.InternalServerError;

                    var error = context.Features.Get<IExceptionHandlerFeature>();
                    if (error != null)
                    
                        context.Response.AddApplicationError(error.Error.Message);
                        await context.Response.WriteAsync(error.Error.Message);
                    
                );
            );
        

附:在我的情况下,我的场景也返回 405 状态错误,原因是,我使用了类似的操作方法并且存在冲突

例如:

    [HttpGet]
    public ActionResult GetAllEmployees()

    [HttpGet]
    public ActionResult GetCustomers()

希望这至少有助于显示准确的错误信息

【讨论】:

我认为这是实现我想要的解决方法,但不是实现相同目标的正确方法。

以上是关于在 asp net core web api v3.0 中启用 CORS 的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Asp.Net core v3.1 中增加上传文件大小

将文件从 ASP.NET Core Web api 发布到另一个 ASP.NET Core Web api

ASP.NET Core Web Api 自动帮助页面

ASP.NET Core Web API

ASP.NET Core Web API 在 API GET 请求中检索空白记录

Asp.Net Core 1.1 消费web api