简体   繁体   English

.NET Core 中的 CORS

[英]CORS in .NET Core

I am trying to enable CORS in .NET Core in this way:我正在尝试以这种方式在 .NET Core 中启用 CORS:

    public IConfigurationRoot Configuration { get; }

    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?}");
         });

    }
}

However, when I am sending a request to my app with Angular 2 I am getting the famous但是,当我使用 Angular 2 向我的应用程序发送请求时,我得到了著名的

"No 'Access-Control-Allow-Origin' header is present on the requested resource." “请求的资源上不存在‘Access-Control-Allow-Origin’标头。”

error message.错误信息。

I am also using Windows Authentication + WebListener.我也在使用 Windows 身份验证 + WebListener。 If I am checking with postman the only response headers are:如果我与邮递员核对,则唯一的响应标头是:

Content-Length →3533 Content-Type →application/json;内容长度→3533 内容类型→应用程序/json; charset=utf-8 Date →Fri, 14 Oct 2016 12:17:57 GMT Server →Microsoft-HTTPAPI/2.0 charset=utf-8 日期 →2016 年 10 月 14 日星期五 12:17:57 GMT 服务器 →Microsoft-HTTPAPI/2.0

So there must be still something wrong configured.所以肯定还是配置有问题。 Any proposals?有什么建议吗?

If I remove the outcommented line it works, but I need Windows Authentication :-(如果我删除了注释行,它可以工作,但我需要 Windows 身份验证:-(

        var host = new WebHostBuilder()
            .UseWebListener()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            //.UseWebListener(options => options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.NTLM)
            .Build();

Assume you have the answer, but for the benefit of searchers, I had the same problem with the standard tutorial on .NET Core Cors .假设你有答案,但为了搜索者的利益,我在.NET Core Cors的标准教程中遇到了同样的问题。

One of the many errors encountered:遇到的众多错误之一:

XMLHttpRequest cannot load localhost:64633/api/blogs. XMLHttpRequest 无法加载 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.对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'localhost:56573' is therefore not allowed access.因此,不允许访问 Origin 'localhost:56573'。 The response had HTTP status code 500.响应的 HTTP 状态代码为 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.要使用它,您可以在控制器或方法上添加EnableCorsAttribute eg例如

[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.当我使用以下代码调用它时(使用标准 js/jQuery 以便于复制和粘贴),通信停止被拒绝。

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.');
        }
    });
}

This way works normally, just tried it on angular2 with .net core.这种方式正常工作,只是在带有.net core的angular2上尝试过。 The issue the OP is having is that this doesnt work with windows authentication. OP 遇到的问题是这不适用于 Windows 身份验证。 I am assuming the middleware for windows authentication is happening before a request comes through, in which case its breaking.我假设用于 Windows 身份验证的中间件在请求通过之前发生,在这种情况下它会中断。 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.最好的办法是看看是否有办法在配置中处理 cors 中间件后启用 windows auth 中间件。

Then the order would be然后顺序是

App.UseCors() App.UseCors()

App.UseWindowsAuth() App.UseWindowsAuth()

App.UseMVC() 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?}");
         });

    }

What the documentation misses, is the importance of .AllowAnyMethod().文档遗漏的是 .AllowAnyMethod() 的重要性。 If not present, the dreaded No 'Access-Control-Allow-Origin' will keep bugging you.如果不存在,可怕的 No 'Access-Control-Allow-Origin' 将继续困扰您。 In your code it's there, so I guess you missed setting the right header in jour client side application.在您的代码中,它就在那里,所以我猜您错过了在 jour 客户端应用程序中设置正确的标头。

I Personally got it to work by allowing all:我个人通过允许所有内容使其工作:

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

And my Angular post function like:我的 Angular 帖子功能如下:

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.之后,您可以通过指定来源等逐渐向上工作。

In ASPNET CORE 2.0, The following works for me在 ASPNET CORE 2.0 中,以下对我有用

   public void ConfigureServices(IServiceCollection services)
    {

        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
        });
        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                builder => builder.WithOrigins("http://localhost:5000").AllowAnyHeader()
                .AllowAnyMethod());
        });

        services.AddMvc()
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        loggerFactory.AddConsole();
        loggerFactory.AddDebug(LogLevel.Information);

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

        // Shows UseCors with named policy.
        app.UseCors("AllowSpecificOrigin");

        app.UseStaticFiles();
        app.UseAuthentication();


        app.UseMvcWithDefaultRoute();
    }
}

Add this section in appsettings.jsonappsettings.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.注意: App:CorsOrigins中的App:CorsOrigins可以包含多个地址,用逗号appsettings.json

You just need to add this in ConfigureService Method of StartUp Class你只需要在 StartUp 类的 ConfigureService 方法中添加这个

services.AddCors ();

and this in Configure Method of Startup Class and it will work fine then这在启动类的配置方法中,它会正常工作

app.UseCors (builder => builder
                 .AllowAnyOrigin ()
                 .AllowAnyHeader ()
                 .AllowAnyMethod ());

There is nothing more to add to enable CORS in .Net Core在 .Net Core 中启用 CORS 无需添加任何内容

I just fixed my problem with Cors in Core 3.1.我刚刚解决了 Core 3.1 中 Cors 的问题。 I was following almost every example and documentation out there.我正在关注几乎所有的示例和文档。 Unfortunately nothing worked until I did .Build() for the builder inside the AddPolicy portion.不幸的是,在我为 AddPolicy 部分中的构建器执行 .Build() 之前,没有任何效果。

        services.AddCors(options => {
            options.AddPolicy(
                name: OrginPolicyKey, 
                builder => builder.WithOrigins("http://localhost:3000")
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .Build() // <--- This right here
            );
        });

Also, other people were mentioning about calling the UseCors(OrginPolicyKey) before the rest of your routing and UseMvc stuff.此外,其他人提到在路由和 UseMvc 的其余部分之前调用 UseCors(OrginPolicyKey)。 That is correct and I saw that Putting UseCors after the route part broke it.这是正确的,我看到在路由部分之后放置 UseCors 破坏了它。 Below is how mine is setup.下面是我的设置方式。

        app.UseCors(OrginPolicyKey); // <--- First

        // Then routing stuff..
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints
                .MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}"
                );
        });

Who knew a builder needs to be built ;D谁知道需要建造一个建造者;D

The answer of @HockeyJ is right, but you can do something more concise if wanted. @HockeyJ 的答案是正确的,但如果需要,您可以做一些更简洁的事情。

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.
     });
}

I encountered CORS issues in my application.我在我的应用程序中遇到了 CORS 问题。 I felt that I properly implemented the logic but was still getting presented with Access-Control-Allow-Origin 403 Error.我觉得我正确地实现了逻辑,但仍然出现 Access-Control-Allow-Origin 403 错误。 I tried every setting mentioned above but nothing worked.我尝试了上面提到的所有设置,但没有任何效果。

I later discovered that my issue wasn't CORS related.后来我发现我的问题与 CORS 无关。 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对控制器的调用正确地传递到方法 OnActionExecuting

public override void OnActionExecuting(ActionExecutingContext context)

The logic within the filter was throwing an exception and was presented as a CORS 403 error.过滤器中的逻辑抛出异常并显示为 CORS 403 错误。

this is actually is a bug in dotnet core.这实际上是 dotnet 核心中的一个错误。

try to add cors policy right in the "Configure" method.尝试在“配置”方法中添加 cors 策略。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseRouting();
        app.UseCors(option =>
            option.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                );
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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