在 ASP.NET Core 中配置 CORS

作者:微信公众号:【架构师老卢】
6-1 8:44
185

先决条件

如果您不熟悉_同源策略 (SOP)_ 或_跨域资源共享 (CORS) 策略_,我强烈建议您阅读我之前的文章 (https://emrebener.medium.com/a-comprehensive-guide-to-the-same-origin-policy-and-the-cors-policy-4ca7535b0145),其中我详细解释了 SOP 和 CORS。本文假定您对这些策略有基本的了解,并重点介绍如何在 ASP.NET Core 环境中配置 CORS。

如果你来这里是为了解决你遇到的错误,我鼓励你先了解所涉及的策略,然后再专注于解决错误。

1. 配置 CORS

在 ASP.NET Core 项目中配置 CORS 以启用跨域请求涉及将 CORS 服务添加到服务容器,然后在管道中注册 CORS 中间件,或使用 CORS 属性启用 CORS。

1.1. 服务注册和策略配置

在 ASP.NET Core 应用程序中配置 CORS 策略的第一步是将 CORS 服务添加到项目中。这是使用该方法实现的,该方法将 CORS 设置作为输入并注册所有必要的服务(如果您好奇,其中包括 CORS 服务本身、默认策略提供程序和各种与选项相关的服务 — 稍后会详细介绍)。AddCors()

通过通话,您可以根据需要注册任意数量的策略。例如;AddCors()

var builder = WebApplication.CreateBuilder(args);  
  
// ...  
  
builder.Services.AddCors(options =>  
{  
    options.AddPolicy(name: "AllowAllOrigins",  
        configurePolicy: policy =>  
        {  
            policy.AllowAnyOrigin()  
                .AllowAnyHeader()  
                .AllowAnyMethod();  
        });  
    options.AddPolicy(name: "AllowOnlySomeOrigins",  
        configurePolicy: policy =>  
        {  
            policy.WithOrigins("https://example1.com",  
                "https://example2.com");  
        });  
});  
  
// ...  
  
var app = builder.Build();  
  
// ...

在本例中,我们注册了两个策略,分别名为“AllowAllOrigins”和“AllowOnlySomeOrigins”。“AllowAllOrigins”策略配置为主动禁用 CORS 策略,而“AllowOnlySomeOrigins”配置为仅允许来自 example1.comexample2.com 的跨域请求。

下一步是使用策略启用 CORS,这将在下一节中介绍。通常,使用中间件方法时,只需要并使用单个策略。

1.2. 中间件注册

若要启用 CORS,可以注册用于在所有端点上启用 CORS 的内置 CORS 中间件,也可以使用端点路由来仅为特定端点启用 CORS。这两种方法将在后面的章节中介绍。UseCors()RequireCors()

CORS 中间件使用添加到服务容器的 CORS 服务在项目中的所有终结点上启用 CORS 策略。CORS 中间件已注册到该方法,该方法可以选择将策略名称作为参数。例如;UseCors()

// ...  
  
var myPolicyName = "MyPolicyName"; // you will specify the exact same string in different places, so assigning policy names to variables avoids potential typo mistakes.  
builder.Services.AddCors(options =>  
{  
  options.AddPolicy(name: myPolicyName,  
    configurePolicy: policy =>  
    {  
        policy.WithOrigins("https://example1.com",  
       "https://example2.com");  
    });  
});  
  
// ...  
  
var app = builder.Build();  
  
app.UseHttpsRedirection();  
app.UseStaticFiles();  
app.UseRouting();  
  
app.UseCors(myPolicyName);  
  
app.UseAuthorization();  
  
// ...

1.2.1. 使用默认策略

通过显式指定默认策略 ,然后可以使用或不需要指定策略名称作为参数。此外,使用默认策略集,可以使用该属性,而无需指定策略名称。这个想法是,当设置默认策略时,CORS 中间件和服务将知道在未显式指定策略时要使用哪个策略。AddDefaultPolicy()UseCors()RequireCors()[EnableCors]

请注意,即使您只注册了一个策略,也只是调用而不指定策略名称也不会启用 CORS。因此,如果您不希望为 、 或 提供策略名称,则需要调用至少一个策略定义。UseCors()AddDefaultPolicy()UseCors()RequireCors()[EnableCors]

添加默认策略与添加任何策略完全相同,只不过您调用而不是 。AddDefaultPolicy()AddPolicy()

1.2.2. 最简单的方法

我想指出的是,在 ASP.NET Core 项目中启用 CORS 有不同的方法。事实是;如果项目中只有一个策略(通常是这种情况),则可以跳过将 CORS 服务添加到服务容器。

这是因为添加的服务主要用于决策(确定要使用的策略)和提供策略配置,当您在项目中只定义了一个策略时,这些配置是不必要的。AddCors

因此,如果您只需要在项目范围内使用单个策略,我的建议是完全避免并直接在调用中指定策略,如下所示;AddCorsUseCors

app.UseCors(configurePolicy: policy =>  
    {  
        policy.WithOrigins("https://example1.com",  
            "https://example2.com");  
    });

在此方法中,将策略本身指定为参数而不是其名称,这样就不需要 CORS 服务。

1.2.3. 关于中间件顺序

与注册中间件一样,您必须谨慎对待 CORS 中间件在管道中的位置。例如,如果使用响应缓存,则不希望在 CORS 中间件之前调用。UseResponseCaching()

1.2.3.1. JavaScript 客户端的重要说明

通常,在 .但是,在使用 JavaScript 客户端(例如 Angular、React)时,必须在 .UseStaticFiles()UseCors()UseCors()UseStaticFiles()

1.3. 启用具有属性的 CORS

正如我所提到的,使用中间件方法可以确保项目中所有端点的 CORS 策略相同。但是,如果您需要精细控制哪些终结点启用了 CORS 以及使用什么策略,则可以使用该属性。[EnableCors]

请务必注意,对这种级别的控制的需求很少,而且很可能不需要使用属性在特定终结点上配置 CORS。

该属性可应用于 Razor 页面 PageModel、控制器或控制器操作方法。您可以使用指定默认策略或指定特定策略。[EnableCors][EnableCors][EnableCors("PolicyNameGoesHere")]

请注意,当该属性应用于终结点并在管道中注册 CORS 中间件时,将应用这两个策略。但是,不建议这样做。您应该选择这两种方法中的任何一种,而不是将它们组合在一起。换句话说。仅当不使用 CORS 中间件时,CORS 属性才相关。[EnableCors]

下面介绍如何使用控制器操作的特定策略启用 CORS;

public class MyController : Controller  
{  
  
  // ...  
  
  [EnableCors("PolicyName")] // enables CORS with the specified policy for this action  
  public IActionResult FunCatFact()  
  {  
    return Ok("A group of cats is called a clowder");  
  }  
      
  // ...  
    
}

1.3.1. [DisableCors]属性

当使用 CORS 中间件 () 禁用特定终结点的 CORS 策略时,或者当您在控制器级别上想要禁用特定控制器操作的 CORS 时,可以使用该属性。例如;[DisableCors]UseCors()[EnableCors]

[EnableCors] // if there is a default policy set, you don't have to specify policy name  
public class MyController : Controller  
{  
  
  // ...  
  
  [DisableCors] // this will disable CORS for this action  
  public IActionResult FunCatFact()  
  {  
    return Ok("A group of cats is called a clowder");  
  }  
   
  // this action will have CORS enabled, since it was enabled on the controller  
  public IActionResult FunDogFact()  
  {  
    return Ok("Dogs dream just like humans do");  
  }  
      
  // ...  
    
}

2. CORS设置详解

本节对每个可配置的 CORS 设置进行说明,详细说明其实际效果以及如何配置它们。

2.1. 允许源

  • AllowAnyOrigin:允许来自所有源的跨域请求,接受任何方案(httphttps)。强烈建议不要使用此设置。
    影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Origin: *policy.AllowAnyOrigin()
  • WithOrigins:指定允许发起跨域请求的源列表。
    影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Originpolicy.WithOrigins("https://example1.com", "https://example2.com")

2.2. 允许方法

  • AllowAnyMethod:允许任何具有跨域请求的 HTTP 方法。
    影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Methods: *policy.AllowAnyMethod()
  • WithMethods:指定跨域请求中允许的方法列表。
    影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Methodspolicy.WithMethods("GET", "POST")

2.3. 允许标头

  • AllowAllHeaders:仅允许跨域请求中的所有标头。影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Headers: *policy.AllowAnyHeader()
  • WithHeaders:指定跨域请求中接受的标头列表。
    影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Headerspolicy.WithHeaders(HeaderNames.AcceptCharset, "X-MyCustomHeader", "X-MyOtherCustomHeader")
  • WithExposedHeaders:指定可向调用脚本公开/显示的标头列表。默认情况下,浏览器会从响应中筛选出所有未列入 CORS 安全列表的标头(有关 CORS 安全列表请求标头的详细细分,您可以参考 CORS 规范)。
  • 影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Expose-Headerspolicy.WithExposedHeaders("X-MyCustomHeader", "X-MyOtherCustomHeader")

您可以使用 指定已知的 HTTP 标头HeaderNames.ContentType

2.4. 允许/禁止凭据请求

  • AllowCredentials:指定是否允许凭据请求。影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Credentials: truepolicy.AllowCredentials()
  • DisallowCredentials:将策略设置为不接受凭据请求。影响; 标头将添加到 CORS 响应中。
    用法;Access-Control-Allow-Credentials: falsepolicy.DisallowCredentials()

2.5. 设置印前检查缓存持续时间

  • SetPreflightMaxAge:指定可以缓存预检响应的持续时间。
    影响; 标头将添加到 CORS 响应中。
    用法; **(**以 55 秒为例)Access-Control-Max-Agepolicy.SetPreflightMaxAge(TimeSpan.FromSeconds(55))

请注意,如果调用了 ,则不能同时调用 、 或在同一策略上,因为 CORS 规范禁止在凭证请求中使用任何通配符。AllowCredentialsAllowAnyOriginAllowAnyMethodAllowAllHeaders

3. 关于将 CORS 卸载到 IIS 的注意事项

正如您可以将 HSTS 和 HTTPS 重定向等任务委派给 IIS 一样,也可以将 CORS 策略的管理委派给 Web 服务器。

如果服务器不允许匿名访问,则 CORS 需要先运行,然后 Windows 身份验证必须在 CORS 之前运行。IIS CORS 模块使这成为可能。

另一方面,您将无法在本地运行项目(如果存在 CORS 错误)。因此,即使您选择在生产环境中将 CORS 卸载到 IIS,您仍然需要通过检查当前开发环境在代码中有条件地注册 CORS 服务和中间件。

相关留言评论
昵称:
邮箱:
阅读排行