如果您不熟悉_同源策略 (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。
如果你来这里是为了解决你遇到的错误,我鼓励你先了解所涉及的策略,然后再专注于解决错误。
在 ASP.NET Core 项目中配置 CORS 以启用跨域请求涉及将 CORS 服务添加到服务容器,然后在管道中注册 CORS 中间件,或使用 CORS 属性启用 CORS。
在 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.com 和 example2.com 的跨域请求。
下一步是使用策略启用 CORS,这将在下一节中介绍。通常,使用中间件方法时,只需要并使用单个策略。
若要启用 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();
// ...
通过显式指定默认策略 ,然后可以使用或不需要指定策略名称作为参数。此外,使用默认策略集,可以使用该属性,而无需指定策略名称。这个想法是,当设置默认策略时,CORS 中间件和服务将知道在未显式指定策略时要使用哪个策略。AddDefaultPolicy()UseCors()RequireCors()[EnableCors]
请注意,即使您只注册了一个策略,也只是调用而不指定策略名称也不会启用 CORS。因此,如果您不希望为 、 或 提供策略名称,则需要调用至少一个策略定义。UseCors()AddDefaultPolicy()UseCors()RequireCors()[EnableCors]
添加默认策略与添加任何策略完全相同,只不过您调用而不是 。AddDefaultPolicy()AddPolicy()
我想指出的是,在 ASP.NET Core 项目中启用 CORS 有不同的方法。事实是;如果项目中只有一个策略(通常是这种情况),则可以跳过将 CORS 服务添加到服务容器。
这是因为添加的服务主要用于决策(确定要使用的策略)和提供策略配置,当您在项目中只定义了一个策略时,这些配置是不必要的。AddCors
因此,如果您只需要在项目范围内使用单个策略,我的建议是完全避免并直接在调用中指定策略,如下所示;AddCorsUseCors
app.UseCors(configurePolicy: policy =>
{
policy.WithOrigins("https://example1.com",
"https://example2.com");
});
在此方法中,将策略本身指定为参数而不是其名称,这样就不需要 CORS 服务。
与注册中间件一样,您必须谨慎对待 CORS 中间件在管道中的位置。例如,如果使用响应缓存,则不希望在 CORS 中间件之前调用。UseResponseCaching()
通常,在 .但是,在使用 JavaScript 客户端(例如 Angular、React)时,必须在 .UseStaticFiles()UseCors()UseCors()UseStaticFiles()
正如我所提到的,使用中间件方法可以确保项目中所有端点的 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");
}
// ...
}
当使用 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");
}
// ...
}
本节对每个可配置的 CORS 设置进行说明,详细说明其实际效果以及如何配置它们。
您可以使用 指定已知的 HTTP 标头HeaderNames.ContentType
请注意,如果调用了 ,则不能同时调用 、 或在同一策略上,因为 CORS 规范禁止在凭证请求中使用任何通配符。AllowCredentialsAllowAnyOriginAllowAnyMethodAllowAllHeaders
正如您可以将 HSTS 和 HTTPS 重定向等任务委派给 IIS 一样,也可以将 CORS 策略的管理委派给 Web 服务器。
如果服务器不允许匿名访问,则 CORS 需要先运行,然后 Windows 身份验证必须在 CORS 之前运行。IIS CORS 模块使这成为可能。
另一方面,您将无法在本地运行项目(如果存在 CORS 错误)。因此,即使您选择在生产环境中将 CORS 卸载到 IIS,您仍然需要通过检查当前开发环境在代码中有条件地注册 CORS 服务和中间件。