简体   繁体   中英

Configure Strict Cors .Net Core 3.1

I have a public analytics web api (.Net Core 3.1) that captures basic analytics from my various web apps and sites (page views, etc). I'd very much like to configure cors in a more strict manner as I am well aware of the origins from where traffic should come. It's worth noting that I'm updating this application from .Net Core 2.2 to .Net Core 3.1 .

I have the following method in my Startup.cs file

public void ConfigureServices(IServiceCollection services)
{
  ...
  ConfigureCors(services);
}

private void ConfigureCors(IServiceCollection services)
{
  // https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas
  services.AddCors(options =>
  {
        options.AddPolicy("CorsPolicy",
             builder => builder.WithOrigins(AppConfiguration.CorsOrigins)
             .AllowAnyMethod()
             .AllowAnyHeader());
  });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      app.UseRouting();
      app.UseCors("CorsPolicy");
      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers().RequireAuthorization();
      });
  }

AppConfiguration is a class I use to handle configurations and it grabs json values using the following:
public string[] CorsOrigins => _config["CorsOrigins"].Split(',');

In appsettings.Development.json , I have "CorsOrigins": "*"

I'd very much like to specify strict origins in the appsettings.Production.json and appsettings.Staging.json files.
Eg "CorsOrigins": "https://subdomain.example.com,https://www.example.com,https://example.com" , but on deployment, I get a status of 502 whenever by websites/apps hit the various endpoints.

"CorsOrigins": "*" works on local so there can't be anything wrong with the Startup.cs file as far as I'm aware.

Update: "CorsOrigins": "*" actually does not work for the staging or production environments either. Now I'm even more confused. To be clear, this is a cors question. The following worked fine before upgrading to .Net Core 3.1 :

private void ConfigureCors(IServiceCollection services)
      services.AddCors(options =>
      {
        options.AddPolicy("CorsPolicy",
             builder => builder.AllowAnyOrigin()
             .AllowAnyMethod()
             .AllowAnyHeader()
             .AllowCredentials());
      });
    }

在此处输入图像描述

Take care to place the UseCors at the right location. From the docs :

The call to UseCors must be placed after UseRouting, but before UseAuthorization.

As noted in the comments, allowing "*" as origin isn't allowed with AllowCredentials.

Here's a working example of a CORS configuration from my ASPNET Core 3.1 project. It does the config in the Configure method instead of ConfigureServices, but same content:

// Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
    // etc
}

public void Configure(IApplicationBuilder app)
{
    // other configs

    app.UseRouting();

    // CORS configuration. Expects allowed origins as comma-separated list in config under 'Cors:AllowedOrigins'.
    string configuredOrigins = Configuration["Cors:AllowedOrigins"] ?? throw new ArgumentNullException("Cors:AllowedOrigins");
    string[] origins = configuredOrigins.Split(',', ';').Select(i => i.Trim()).ToArray();
    app.UseCors(policy => policy
        .WithOrigins(origins)
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials() // Required by SignalR
        .WithExposedHeaders(CONTINUATION_HEADER_KEY) // Allow use of custom header
        .SetPreflightMaxAge(TimeSpan.FromSeconds(86400))); // Allow caching for 24 hours (depends on browser)

    app.UseAuthentication();
    app.UseAuthorization();

    // other configs
}

Sorry this is a difficult question so there could be a number of reasons it doesnt work but Ive run into a similar issue and resolved its by altering the cors invocation in the Configure() function. The Configure() function is a gets called during runtime and acts as an http request pipeline so in some cases order of execution matters ( https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-3.1#the-configure-method )

You could try the following:

Change the current:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      app.UseRouting();
      app.UseAuthentication();
      app.UseAuthorization();
      app.UseCors("CorsPolicy"); //Move this line 

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers().RequireAuthorization();
      });
  }

To:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      app.UseRouting();

      app.UseCors("CorsPolicy"); // Here

      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers().RequireAuthorization();
      });
  }

Hence the first operation in the http pipeline would be to validate cors. I rate this is a fair bet as from your question it sounds like you dont get an app initialise error but rather a runtime client request time error. I dont know for certain if this will solve the problem but maybe it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM