CORS in .NET Core

前端 未结 10 1071
失恋的感觉
失恋的感觉 2020-12-04 23:30

I am trying to enable CORS in .NET Core in this way:

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollecti         


        
相关标签:
10条回答
  • 2020-12-04 23:58

    Add this section in appsettings.json

    "App": {
      "CorsOrigins": "http://yourdomain"
    }
    

    and

    services.AddCors(options => {
      options.AddPolicy(DefaultCorsPolicyName, builder => {
    
       builder.WithOrigins(
         _appConfiguration["App:CorsOrigins"]
           .Split(",", StringSplitOptions.RemoveEmptyEntries)
           .Select(o => o.RemovePostFix("/"))
           .ToArray()
       ).SetIsOriginAllowedToAllowWildcardSubdomains()
        .AllowAnyHeader()
        .AllowAnyMethod()
        .AllowCredentials();
      });
    });
    

    Note: App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.

    0 讨论(0)
  • 2020-12-05 00:00

    I encountered CORS issues in my application. I felt that I properly implemented the logic but was still getting presented with Access-Control-Allow-Origin 403 Error. I tried every setting mentioned above but nothing worked.

    I later discovered that my issue wasn't CORS related. I implemented a custom attribute

    [Route("v1/[Controller]")]
    [ServiceFilter(typeof(MyCustomFilterAttribute))]
    public class MySpecialListsController 
    

    Calls made to the controller were properly making it to the method OnActionExecuting

    public override void OnActionExecuting(ActionExecutingContext context)
    

    The logic within the filter was throwing an exception and was presented as a CORS 403 error.

    0 讨论(0)
  • 2020-12-05 00:03

    Assume you have the answer, but for the benefit of searchers, I had the same problem with the standard tutorial on .NET Core Cors.

    One of the many errors encountered:

    XMLHttpRequest cannot load localhost:64633/api/blogs. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost:56573' is therefore not allowed access. The response had HTTP status code 500.

    After playing around, the following code worked. Full class posted below to aid understanding of what goes where.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.AspNetCore.Cors.Infrastructure;
    
    namespace NetCoreWebApiTesting
    {
        public class Startup
        {
            public Startup(IHostingEnvironment env)
            {
                var builder = new ConfigurationBuilder()
                    .SetBasePath(env.ContentRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    
                if (env.IsEnvironment("Development"))
                {
                    // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
                    builder.AddApplicationInsightsSettings(developerMode: true);
                }
    
                builder.AddEnvironmentVariables();
                Configuration = builder.Build();
            }
    
            public IConfigurationRoot Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container
            public void ConfigureServices(IServiceCollection services)
            {
                // Add framework services.
                services.AddApplicationInsightsTelemetry(Configuration);
    
                services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling =
                                                                Newtonsoft.Json.ReferenceLoopHandling.Ignore);
    
                // ********************
                // Setup CORS
                // ********************
                var corsBuilder = new CorsPolicyBuilder();
                corsBuilder.AllowAnyHeader();
                corsBuilder.AllowAnyMethod();
                corsBuilder.AllowAnyOrigin(); // For anyone access.
                //corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don't add a forward slash on the end!
                corsBuilder.AllowCredentials();
    
                services.AddCors(options =>
                {
                    options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
            {
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
    
                app.UseApplicationInsightsRequestTelemetry();
    
                app.UseApplicationInsightsExceptionTelemetry();
    
                app.UseMvc();
    
                // ********************
                // USE CORS - might not be required.
                // ********************
                app.UseCors("SiteCorsPolicy");
            }
        }
    }
    

    To use it you can add the EnableCorsAttribute either on the controller or on the method. e.g.

    [EnableCors("SiteCorsPolicy")]
    [Route("api/[controller]")]
    public class BlogsController : Controller
    {
    
    }
    

    or

    // POST api/value
    [EnableCors("SiteCorsPolicy")]
    [HttpPost]
    public HttpResponseMessage Post([FromBody]Blog value)
    {
        // Do something with the blog here....
    
        var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
        return msg;
    
    }
    

    When I called this using the following code (using standard js/jQuery for easy of copy and paste), the communication stopped being rejected.

    function HandleClick() {
    
        var entityData = {
            "blogId": 2,
            "url": "http://blog.com/blog1",
            "posts": [
            {
                "postId": 3,
                "title": "Post 1-1",
                "content": "This is post 1 for blog 1",
                "blogId": 2
            },
            {
                "postId": 4,
                "title": "Post 1-2",
                "content": "This is post 2 for blog 1",
                "blogId": 2
            }
            ]
        };
    
        $.ajax({
            type: "POST",
            url: "http://localhost:64633/api/blogs",
            async: true,
            cache: false,
            crossDomain: true,
            data: JSON.stringify(entityData),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (responseData, textStatus, jqXHR) {
                var value = responseData;
            },
            error: function (responseData, textStatus, errorThrown) {
                alert('POST failed.');
            }
        });
    }
    
    0 讨论(0)
  • 2020-12-05 00:12

    This way works normally, just tried it on angular2 with .net core. The issue the OP is having is that this doesnt work with windows authentication. I am assuming the middleware for windows authentication is happening before a request comes through, in which case its breaking. Best bet would be to see if there is a way to enable the windows auth middleware after the cors middleware has processed in Configure.

    Then the order would be

    App.UseCors()

    App.UseWindowsAuth()

    App.UseMVC()

    They must happen in this order for it to work.

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                        .AllowAnyMethod()
                                                                         .AllowAnyHeader()));     
            services.AddMvc();            
        }
    
        public void Configure(IApplicationBuilder app)
        {
            app.UseCors("AllowAll");
    
            app.UseMvc(routes =>
             {
                 routes.MapRoute(
                     name: "default",
                     template: "{controller=Home}/{action=Index}/{id?}");
             });
    
        }
    
    0 讨论(0)
  • 2020-12-05 00:13

    The answer of @HockeyJ is right, but you can do something more concise if wanted.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    
        //Or if you want to chose what to include
        services.AddMvcCore()
                .AddCors()
                (...)
    }
    
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //Cors
        app.UseCors(builder =>
        {
            builder.AllowAnyHeader();
            builder.AllowAnyMethod();
            builder.AllowCredentials();
            builder.AllowAnyOrigin(); // For anyone access.
            //corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url.
         });
    }
    
    0 讨论(0)
  • 2020-12-05 00:15

    What the documentation misses, is the importance of .AllowAnyMethod(). If not present, the dreaded No 'Access-Control-Allow-Origin' will keep bugging you. In your code it's there, so I guess you missed setting the right header in jour client side application.

    I Personally got it to work by allowing all:

    app.UseCors(b => b.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
    

    And my Angular post function like:

    post(model) {
    
        let headers = new Headers({
          'Content-Type':'application/json; charset=utf-8;' 
          ,'Accept':'*/*'
        });
    
    
        let options = new RequestOptions({ headers: headers });
        let body = JSON.stringify(model);
    
        return this.http.post(
          'http://localhost:58847/api/TestPost', body, options)
          .map((response: Response) => {
            let res = response.json();
            return res;
          }
        );
    }
    

    After that, you gradually work your way up by specifying origins etc.

    0 讨论(0)
提交回复
热议问题