ASP.NET Core 为特定控制器禁用 CORS

Posted

技术标签:

【中文标题】ASP.NET Core 为特定控制器禁用 CORS【英文标题】:ASP.NET Core Disable CORS for specific controllers 【发布时间】:2019-03-03 04:51:00 【问题描述】:

我的应用程序中有不同的控制器集(比如说 A 和 B)。需要为 B 控制器启用和禁用 A 控制器的 CORS。 我通过以下方式通过策略配置了 CORS:

ConfigureServices 方法:

services.AddCors(
    options =>
    
        options.AddPolicy(
            "AllowCors",
            builder =>
                
                    builder.AllowAnyOrigin().WithMethods(
                        HttpMethod.Get.Method,
                        HttpMethod.Put.Method,
                        HttpMethod.Post.Method,
                        HttpMethod.Delete.Method).AllowAnyHeader().WithExposedHeaders("CustomHeader");
                );
    );
services.AddMvcCore()

配置方法

app.UseCors("AllowCors");
app.UseMvc();

A 组控制器具有 EnableCors 属性

[EnableCors("AllowCors")]
public class ControllerA1: Controller

CORS 按预期适用于一组 A 控制器(通过浏览器测试)。但是,它也适用于 B 控制器!我什至尝试使用 DisableCors 属性显式禁用 CORS:

[DisableCors]
public class ControllerB1: Controller

但是,无论如何都可以从 UI 请求 ControllerB1 控制器。

B1 控制器的浏览器标题

请求

Provisional headers are shown
Origin: http://localhost:5000
Referer: http://localhost:5000/all
User-Agent: Mozilla/5.0 AppleWebKit Chrome/69 Safari/537

回应

Request URL: http://XX.XX.XX.XX/getall
Request Method: GET
Status Code: 200 OK
Remote Address: XX.XX.XX.XX:80
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: CustomCount        
Content-Type: application/xml; charset=utf-8
Server: Kestrel

您能否建议如何为特定控制器禁用 CORS?

【问题讨论】:

你如何在同一台机器上测试这个? 在不同的机器上测试,UI是localhost,API部署在远程服务器上。我在问题中添加了请求/响应标头 【参考方案1】:

在您的示例中,您在设置 WebHost 时做了两件事:

    创建了一个名为 AllowCors 的自定义 CORS 策略。 向管道添加了 CORS 中间件,该管道使用 AllowCors 作为其 policyName

这是为 CORS 中间件调用的 Invoke 函数的 sn-p:

public async Task Invoke(HttpContext context)

    if (context.Request.Headers.ContainsKey(CorsConstants.Origin))
    
        var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName);
        if (corsPolicy != null)
        
            var corsResult = _corsService.EvaluatePolicy(context, corsPolicy);
            _corsService.ApplyResult(corsResult, context.Response);

    ...

在这个 sn-p 中,_policynull_corsPolicyNameAllowCors。因为AllowCors 是使用AddCors 添加的有效策略的名称,这会导致CORS 中间件为所有请求应用相关的CORS 标头。

在您的示例中,您还使用了 [EnableCors(...)][DisableCors],它们是 MVC 授权过滤器。通过这样做,您主要是告诉 MVC 处理 CORS,它与您添加到 WebHost 管道的 CORS 中间件独立

MVC 和 CORS 中间件的这种组合导致了您意想不到的结果。中间件将 CORS 标头添加到您的请求中不管您是否要求它不要使用 [DisableCors] 属性 - CORS 中间件不知道这个 MVC 概念(过滤器) 甚至存在。

根据此信息,您可以通过以下两种方式之一解决您的问题:

    从您对UseCors 的调用中删除policyName 参数。 删除 UseCors 调用本身。

如果使用选项 1,UseCors 中间件将使用默认策略,前提是它已在传递给 AddCors 委托的 CorsOptions 上使用 AddDefaultPolicy 进行配置。

使用选项 2,CORS 中间件简单地从管道中排除。这也适用于您的示例,因为您在需要的地方使用了[EnableCors(...)]。这也意味着您根本不需要使用 [DisableCors] - 它默认不添加 CORS 标头。

这就提出了一个问题:[DisableCors] 什么时候有用?例如,考虑以下基本控制器:

[EnableCors("AllowCors")]
public class ExampleController : ControllerBase

    public IActionResult Action1() =>
        ...

    public IActionResult Action2() =>
        ...

很明显,在此示例中,Action1Action2 都将设置 CORS 标头。如果您希望Action2 设置标题,您可以使用[DisableCors] 对其进行注释。

【讨论】:

【参考方案2】:

app.useCors 的顺序很重要

//...
app.UseRouting();
app.UseCors("customPolicy");
app.UseEndpoints(...)
//...

【讨论】:

以上是关于ASP.NET Core 为特定控制器禁用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 中优雅的进行响应包装

asp.net core mvc权限控制:分配权限

根据 ASP.NET Core 和 Entity Framework Core 中的条件禁用 [必需] 属性

从 ASP.NET CORE Web Api 获取 React 中的特定响应标头(例如,Content-Disposition)

Asp.Net Core Identity - 没有角色表的简单授权

如何在 ASP.NET Core(.NET 6、VS 2022)中禁用浏览器链接