【问题标题】:Can't enable CORS in ASP.Net Core web api无法在 ASP.Net Core Web api 中启用 CORS
【发布时间】:2019-02-11 17:22:21
【问题描述】:

我创建了一个带有单个控制器的 ASP.Net CORE Web API 项目,现在想从客户端 (React) Web 应用程序调用它。

但是,调用失败并显示“请求的资源上不存在 'Access-Control-Allow-Origin' 标头。”。

从 Fiddler 调用同一端点时,预期的响应标头不存在。

感谢 ATerry,我有进一步的见解:标头不存在,因为 React Web 应用程序和 .Net Core Web API 托管在同一个盒子上。 React 填充与(API)框相同的请求 Origin: 标头,因此服务器(非常聪明)不会添加 Allow-... 响应标头。但是,由于缺少这些标头,React 应用程序拒绝响应。

我正在使用 .Net Core v2.1(撰写本文时的最新版本)。

我基于

构建了代码

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

我检查了这些

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

CORS in .NET Core

How to enable CORS in ASP.NET Core

...但没有一个建议奏效。

有什么想法吗?

这是我配置 .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();
    }
}

上述操作失败后,我也将 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;
    }
}

我得到的响应头:

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

缺少的标题是:

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

【问题讨论】:

  • 您是否将请求中的origin 标头设置为您当前域以外的其他内容?如果不是跨域请求,API 足够智能,可以排除标头。
  • 很好的观察,谢谢。在测试中,我在服务器盒子上发起了来自 Fiddler 的请求。添加请求标头“origin:somethingelse”时,响应确实具有预期的标头。我刚刚从同一个子网中的另一个盒子测试它,结果相同:在没有原始请求标头的情况下调用时,Access-Control-Allow-... 响应标头丢失,当我添加请求标头时它们是正确的返回。
  • CORS是双向确认,Client需要请求CORS,Server需要接受
  • @Richard Hubley 你能给我一个关于如何做到这一点的指针吗?我发现了许多与其他服务器类型类似的案例(比如这个节点 js 服务器仅描述了我的问题:elegantcode.com/2018/06/10/…),但它们都提到了服务器端解决方案:服务器必须提供适当的响应标头。与客户无关。
  • @balintn 作为客户端,您使用什么?看起来你已经通过添加标题解决了邮递员的问题。您仍然对哪个客户有问题?

标签: asp.net reactjs .net-core cors


【解决方案1】:

我相信它应该也适用于 LOCALHOST 托管,只需执行以下更改和删除以及任何额外的更改/配置。

替换这个:

        // 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.AddCors();

并替换这个:

app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

用这个:

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

注意:

  • 即使您的 Web Api 和 React 应用程序配置在 LOCALHOST 上并不意味着它们来自同一来源,这是因为它们托管在不同的端口上,例如 React 应用程序托管在 LOCALHOST:3000 上,而 Web Api 是托管在 LOCALHOST:5000 上。如果客户端(react 应用程序)从不同的端口请求,Web api 会抱怨。

  • 以上 Web Api 代码将允许任何 ORIGIN,在生产应用程序中这是不安全的,因此您需要允许特定 ORIGIN 访问 CORS。

【讨论】:

    【解决方案2】:

    设法通过将用于访问服务器的 URL 从基于 localhost 的 URL 更改为基于 IP 地址的 URL(localhost/api 到 192.168.1.96/api)来解决这个问题。

    似乎 ATerry 提到的部分过滤是基于主机名的:如果主机名是 localhost,IIS 不会发送 Allow-... 标头。问题是 React 需要它们。

    【讨论】:

      【解决方案3】:

      您可以尝试如下说明:https://docs.microsoft.com/en-us/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!");
          });
      }
      

      在您的场景中,它可以更改为类似于下面的代码。

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

      此代码可能看起来与您的代码没有任何不同,但是在定义操作(您称之为构建器)的方式上存在细微差别。我希望这会有所帮助,祝你好运! :)

      【讨论】:

        【解决方案4】:

        我最近遇到了同样的问题,但怀疑我的问题是否与 CORS 相关。因此,我将应用程序部署到本地 IIS 以检查是否会以某种方式解决。然后检查日志,发现与数据模型中的循环引用有关的问题 - “检测到属性的自引用循环......”。在 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;
                        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-13
          • 2017-11-22
          • 1970-01-01
          • 1970-01-01
          • 2017-12-16
          • 2019-01-24
          • 2017-02-08
          • 2017-05-03
          相关资源
          最近更新 更多