无法在面向 netcoreapp3.0 的 ASP.NET Core WebApp 中为特定 API 控制器启用 CORS

Posted

技术标签:

【中文标题】无法在面向 netcoreapp3.0 的 ASP.NET Core WebApp 中为特定 API 控制器启用 CORS【英文标题】:Can't enable CORS for specific API controllers in ASP.NET Core WebApp targeting netcoreapp3.0 【发布时间】:2019-12-26 19:02:23 【问题描述】:

我正在尝试为 ASP.NET Core 应用程序中的特定 API 控制器启用 CORS。首先,我安装 NuGet 包,并将其添加到我的.csproj

<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />

然后,我在ConfigureServices 中添加以下内容:

services.AddCors(options => 
    options.AddPolicy("AllowAll", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
);

之后,如果我在我的Configure 中添加它,它会起作用:

app.UseCors("AllowAll");

但是,这会为所有控制器启用 CORS。我只想为SessionApiController 启用它。如果我改为将 EnableCorsAttribute 添加到控制器:

[Route("api/session")]
[EnableCors("AllowAll")]
[ApiController]
public class SessionApiController : Controller 
    [...]

    [Route("init")]
    public JsonResult InitSession() 
        [...]
    

...它不起作用,当我尝试访问 /api/session/init 端点时,Chrome 给我一个 CORS 错误(“请求的资源上不存在‘Access-Control-Allow-Origin’标头。” )。我在这里错过了什么?

【问题讨论】:

CORS 必须在 API 端激活,您可以接受所有标头,但必须通过 Access-Control-Allow-Headers: * 在服务器端完成 代码 LGTM。如果你改为装饰控制器方法会发生什么?你能提供你的设置的复制品吗? @Jota.Toledo 装饰控制器方法仍然不会添加 CORS 标头。我想我可以想出一个最小的复制品。 @Jota.Toledo 我已经基于可从我的 Github 帐户克隆的 .NET Core WebAPI 模板设置了一个最小复制:github.com/jez9999/CorsTest @Jota.Toledo 如果您将示例 JS 放在另一个来源的网页上(在页面中包含 jQuery 之后),它将无法工作,因为 CORS 策略没有生效,即使有控制器上的 [EnableCors("AllowAll")] 属性。如果属性在方法上,这同样适用。如果你在启动时取消注释app.UseCors("AllowAll");,它会起作用。 【参考方案1】:

考虑以下一个 ASP.NET Core WebApp:

App.csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
  </ItemGroup>
</Project>

Startup.cs 中提取:

    public void ConfigureServices(IServiceCollection services) 
        services.AddCors(options => 
            options.AddPolicy("AllowAll", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        );

        services.AddControllers();
    

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
        app.UseCors();  // Doesn't work
        //app.UseCors("AllowAll");  // Works

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

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints => 
            endpoints.MapControllers();
        );
    

从要应用AllowAll 策略的控制器中提取:

[EnableCors("AllowAll")]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

为了在其中正确应用 CORS,您需要将以下更改应用到代码中,如 migration MS docs 中所述:

    删除deprecated Microsoft.AspNetCore.* packages,在您的情况下为Microsoft.AspNetCore.Cors。这会导致您的 .csproj 看起来像:
 <Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
      <TargetFramework>netcoreapp3.0</TargetFramework>
    </PropertyGroup>
  </Project>

    请仔细遵循 msdocs 中的middleware migration advice,因为顺序很重要!。这导致Startup#Configure 如下所示:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        app.UseRouting();
    
        // AFAIK in netcoreapp2.2 this was not required
        // to use CORS with attributes.
        // This is now required, as otherwise a runtime exception is thrown
        // UseCors applies a global CORS policy, when no policy name is given
        // the default CORS policy is applied
        app.UseCors(); 
    
        if (env.IsDevelopment()) 
            app.UseDeveloperExceptionPage();
        
    
        app.UseHttpsRedirection();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints => 
            endpoints.MapControllers();
        );
    
    

【讨论】:

是的,也解决了这个问题。基本上这两个问题是:我需要删除 Microsoft.AspNetCore.Cors 包引用 - 这显然是 .NET Core 3.0 中内置的 - 我需要将 app.UseCors() 移动到 after app.UseRouting() - 正如你所说,订单很重要。

以上是关于无法在面向 netcoreapp3.0 的 ASP.NET Core WebApp 中为特定 API 控制器启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

带有选项字段的 F# 记录在 Asp.Net WebApi 2.x 应用程序中无法正确反序列化

学习asp.net已经有3个月了,重新整理一下面向对象

在 ASP.NET 中加密 cookie

面向对象

学习ASP.NET比较完整的流程!

Asp.net 面向接口框架之应用程序上下文作用域组件