简体   繁体   English

无法在ASP.Net Core Web API中启用CORS

[英]Can't enable CORS in ASP.Net Core web api

I created an ASP.Net CORE web API project, with a single controller, and would now like to call it from a client (React) web app. 我创建了一个具有单个控制器的ASP.Net CORE Web API项目,现在想从客户端(反应)Web应用程序中调用它。

However, the call fails with "No 'Access-Control-Allow-Origin' header is present on the requested resource.". 但是,调用失败,并且“所请求的资源上没有'Access-Control-Allow-Origin'标头。”。

When calling the same endpoint from Fiddler, the expected response headers are not present. 从Fiddler调用同一终结点时,预期的响应头不存在。

Thanks to ATerry, I have further insight: the headers are not present, because the React web app and the .Net Core web API are hosted on the same box. 多亏了ATerry,我才有了更深入的了解:标头不存在,因为React Web应用程序和.Net Core Web API托管在同一框中。 React populates the request Origin: header which is the same as the (API) box, thus the server (being really clever about it) does not add the Allow-... response headers. React填充了请求Origin:标头,该标头与(API)框相同,因此服务器(真的很聪明)不会添加Allow -...响应标头。 However, the React app rejects the response, because of the lack of those headers. 但是,由于缺少这些标头,因此React应用拒绝响应。

I'm using .Net Core v2.1 (latest as of this writing). 我正在使用.Net Core v2.1(本文撰写时为最新)。

I built the code based on 我建立了基于

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1 https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1

I checked these 我检查了这些

https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas

CORS in .NET Core .NET Core中的CORS

How to enable CORS in ASP.NET Core 如何在ASP.NET Core中启用CORS

... but none of the suggestions worked. ...但是所有建议都没有奏效。

Any ideas? 有任何想法吗?

This is how I configure the .Net Core app (code changed from actual to try and allow anything): 这是我配置.Net Core应用程序的方式(代码从实际更改为尝试并允许任何操作):

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    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)
    {
        // Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
        // See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
        services.AddCors(options =>
        {
            options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
                .AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials());
        });

        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)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

Having failed with just the above, I added the CORS attributes to the controller class and controller methods too: 由于上述原因而失败,我也将CORS属性添加到控制器类和控制器方法中:

[Route("api/[controller]")]
[ApiController]
[EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
public class DealsController : ControllerBase
{
[...]
[HttpGet]
    [EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
    public ActionResult<List<Deal>> GetAll()
    {
        return Store;
    }
}

The response headers I get: 我得到的响应头:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-Powered-By: ASP.NET
Date: Thu, 06 Sep 2018 12:23:27 GMT

The missing headers are: 缺少的标题是:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000

I believe it should work fine with LOCALHOST hosting as well, just do below changes and remove and any extra changes/configurations. 我相信它也可以与LOCALHOST托管一起正常工作,只需执行以下更改和删除以及任何其他更改/配置即可。

Replace this: 替换为:

        // Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
    // See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
    services.AddCors(options =>
    {
        options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
            .AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials());
    });

with this: 有了这个:

services.AddCors();

and Replace this: 并替换为:

app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

with this: 有了这个:

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

NOTE: 注意:

  • Even if your Web Api and React app are configured on LOCALHOST doesn't mean they are from same origin, it is because they are hosted on different port like react app is hosted on LOCALHOST:3000 and Web Api is hosted on LOCALHOST:5000. 即使您的Web Api和React应用程序在LOCALHOST上配置并不意味着它们来自同一来源,这是因为它们托管在不同的端口上,例如react app托管在LOCALHOST:3000上,而Web Api托管在LOCALHOST:5000上。 Web api will complaint if client(react app) is requesting from different port. 如果客户端(反应应用)从其他端口请求,Web api将会投诉。

  • Above Web Api code will allow ANY ORIGIN and in production applications this is not safe so you need to allow specific ORIGIN to CORS access. 上面的Web Api代码将允许任何ORIGIN,并且在生产应用程序中这是不安全的,因此您需要允许特定的ORIGIN访问CORS。

You could try something like below as explained here: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2 您可以尝试如下所述,如下所示: https : //docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-2.2

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("AllowSpecificOrigin",
            builder => builder.WithOrigins("http://example.com"));
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

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

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

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("Hello World!");
    });
}

In your scenario it could be changed to something like the code below. 在您的方案中,可以将其更改为类似于下面的代码。

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    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.AddCors(options => options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME,
                builder =>
                {
                    builder.AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                }));

        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)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

This code might not look any different from yours however, there is a slight difference in the way the actions(what you call the builder) are defined. 这段代码看起来可能与您的代码没有什么不同,但是定义动作(您称其为构建器)的方式略有不同。 I hope that helps, good luck! 希望对您有帮助,祝您好运! :) :)

Managed to solve it by changing the URL used to access the server from a localhost based one to an IP address based one (localhost/api to 192.168.1.96/api). 通过将用于访问服务器的URL从基于localhost的URL更改为基于IP地址的URL(将localhost / api更改为192.168.1.96/api)来解决该问题。

It seems that part of the filtering that ATerry mentioned is based on host name: IIS doesn't send the Allow-... headers if hostname is localhost. 看来,ATerry提到的部分过滤是基于主机名的:如果主机名是localhost,则IIS不会发送Allow -...标头。 Trouble is that React requires them. 问题是React需要它们。

I got stuck with this same issue recently but doubted if mine was CORS related. 我最近也遇到了同样的问题,但是怀疑我的问题是否与CORS有关。 So I went to deploy the app to my local IIS to check if that will get resolved somehow. 因此,我去了将应用程序部署到本地IIS,以检查是否可以解决该问题。 Then checked the logs and found an issue pertaining to circular reference in data models - "Self referencing loop detected for property..". 然后检查日志,发现与数据模型中的循环引用有关的问题-“检测到属性的自我引用循环。”。 Applied an action in Startup.js to resolve the issue like so, 在Startup.js中应用了一个操作来解决此问题,

    services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.Formatting = Formatting.Indented;

                    // this line
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                });

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

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