马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

在 ASP.NET Core 中启用跨域请求(CORS)

[复制链接]
查看4143 | 回复0 | 2019-11-8 09:52:03 | 显示全部楼层 |阅读模式

本文先容怎样在 ASP.NET Core 的应用程序中启用 CORS。

欣赏器安全可以防止网页向其他域发送哀求,而不是为网页提供服务。 此限定称为相同源计谋。 同一源计谋可防止恶意站点读取另一个站点中的敏感数据。 有时,你大概想要答应其他站点对你的应用举行跨域哀求。 有关详细信息,请参阅MOZILLA CORS 一文

跨源资源共享(CORS):

  • 是一种 W3C 标准,可让服务器放宽相同的源计谋。
  • 不是一项安全功能,CORS 放宽 security。 API 不能通过答应 CORS 来更安全。 有关详细信息,请参阅CORS 的工作原理。
  • 答应服务器明白答应一些跨源哀求,同时拒绝其他哀求。
  • 比早期的技能(如JSONP)更安全且更机动。

查察或下载示例代码怎样下载

同一原点

如果两个 Url 具有相同的方案、主机和端口(RFC 6454),则它们具有相同的源。

这两个 Url 具有相同的源:

  • https://example.com/foo.html
  • https://example.com/bar.html

这些 Url 的劈头差别于前两个 Url:

  • https://example.net – 个差别的域
  • https://www.example.com/foo.html – 个差别的子域
  • http://example.com/foo.html – 个差别的方案
  • https://example.com:9000/foo.html – 个差别端口

比力泉源时,Internet Explorer 不会思量该端口。

具有定名计谋和中间件的 CORS

CORS 中间件处理惩罚跨域哀求。 以下代码通过指定源为整个应用启用 CORS:

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
  8. public IConfiguration Configuration { get; }
  9. public void ConfigureServices(IServiceCollection services)
  10. {
  11. services.AddCors(options =>
  12. {
  13. options.AddPolicy(MyAllowSpecificOrigins,
  14. builder =>
  15. {
  16. builder.WithOrigins("http://example.com",
  17. "http://www.contoso.com");
  18. });
  19. });
  20. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  21. }
  22. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  23. {
  24. if (env.IsDevelopment())
  25. {
  26. app.UseDeveloperExceptionPage();
  27. }
  28. else
  29. {
  30. app.UseHsts();
  31. }
  32. app.UseCors(MyAllowSpecificOrigins);
  33. app.UseHttpsRedirection();
  34. app.UseMvc();
  35. }
  36. }
复制代码

前面的代码:

  • 将计谋名称设置为 "_myAllowSpecificOrigins"。 计谋名称为恣意名称。
  • 调用 UseCors 扩展方法,这将启用 CORS。
  • 使用lambda 表达式调用 AddCors。 Lambda 采取 @no__t 0 对象。 本文稍后将先容设置选项,如 WithOrigins

@No__t-0 方法调用将 CORS 服务添加到应用的服务容器:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddCors(options =>
  4. {
  5. options.AddPolicy(MyAllowSpecificOrigins,
  6. builder =>
  7. {
  8. builder.WithOrigins("http://example.com",
  9. "http://www.contoso.com");
  10. });
  11. });
  12. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  13. }
复制代码

有关详细信息,请参阅本文档中的CORS 计谋选项

@No__t-0 方法可以链接方法,如以下代码所示:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddCors(options =>
  4. {
  5. options.AddPolicy(MyAllowSpecificOrigins,
  6. builder =>
  7. {
  8. builder.WithOrigins("http://example.com",
  9. "http://www.contoso.com")
  10. .AllowAnyHeader()
  11. .AllowAnyMethod();
  12. });
  13. });
  14. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  15. }
复制代码

留意: URL不得包罗尾随斜杠(/)。 如果 URL 以 / 制止,比力将返回 false,而且不返回任何标头。

将 CORS 计谋应用到全部闭幕点

以下代码通过 CORS 中间件将 CORS 计谋应用到全部应用闭幕点:

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. // Preceding code ommitted.
  4. app.UseRouting();
  5. app.UseCors();
  6. app.UseEndpoints(endpoints =>
  7. {
  8. endpoints.MapControllers();
  9. });
  10. // Following code ommited.
  11. }
复制代码

告诫

通过闭幕点路由,CORS 中间件必须设置为在对 @no__t 和 UseEndpoints 的调用之间实行。 设置不正确将导致中间件制止正常运行。

请参阅在 Razor Pages、控制器和操纵方法中启用 cors,以在页面/控制器/操纵级别应用 cors 计谋。

有关测试上述代码的说明,请参阅测试 CORS

使用闭幕点路由启用 Cors

使用闭幕点路由,可以根据每个闭幕点启用 CORS,使用 @no__t 的扩展方法集。

  1. app.UseEndpoints(endpoints =>
  2. {
  3. endpoints.MapGet("/echo", async context => context.Response.WriteAsync("echo"))
  4. .RequireCors("policy-name");
  5. });
复制代码

同样,也可以为全部控制器启用 CORS:

  1. <code data-author-content="app.UseEndpoints(endpoints =>
  2. {
  3. endpoints.MapControllers().RequireCors("policy-name");
  4. });
  5. ">app.UseEndpoints(endpoints => { endpoints.MapControllers().RequireCors("policy-name"); });
  6. </code>
复制代码

使用属性启用 CORS

@No__t-1EnableCors @ no__t属性提供了一种用于全局应用 CORS 的更换方法。 @No__t-0 特性可为选定的闭幕点(而不是全部闭幕点)启用 CORS。

使用 @no__t 指定默认计谋,并 [EnableCors("{Policy String}")] 指定计谋。

@No__t-0 特性可应用于:

  • Razor 页 PageModel
  • 控制器
  • 控制器操纵方法

您可以将差别的计谋应用于控制器/页面模子/操纵,[EnableCors] 属性。 将 [EnableCors] 属性应用于控制器/页面模子/操纵方法,并在中间件中启用 CORS 时,将应用这两种计谋。 发起不要联合计谋。 使用同一个应用中的 [EnableCors] 特性或中间件。

下面的代码将差别的计谋应用于每个方法:

  1. [Route("api/[controller]")]
  2. [ApiController]
  3. public class WidgetController : ControllerBase
  4. {
  5. // GET api/values
  6. [EnableCors("AnotherPolicy")]
  7. [HttpGet]
  8. public ActionResult<IEnumerable<string>> Get()
  9. {
  10. return new string[] { "green widget", "red widget" };
  11. }
  12. // GET api/values/5
  13. [EnableCors] // Default policy.
  14. [HttpGet("{id}")]
  15. public ActionResult<string> Get(int id)
  16. {
  17. switch (id)
  18. {
  19. case 1:
  20. return "green widget";
  21. case 2:
  22. return "red widget";
  23. default:
  24. return NotFound();
  25. }
  26. }
  27. }
复制代码

  1. <code data-author-content="[Route("api/[controller]")]
  2. [ApiController]
  3. public class WidgetController : ControllerBase
  4. {
  5. // GET api/values
  6. [EnableCors("AnotherPolicy")]
  7. [HttpGet]
  8. public ActionResult<IEnumerable<string>> Get()
  9. {
  10. return new string[] { "green widget", "red widget" };
  11. }
  12. // GET api/values/5
  13. [EnableCors] // Default policy.
  14. [HttpGet("{id}")]
  15. public ActionResult<string> Get(int id)
  16. {
  17. switch (id)
  18. {
  19. case 1:
  20. return "green widget";
  21. case 2:
  22. return "red widget";
  23. default:
  24. return NotFound();
  25. }
  26. }
  27. }
  28. "></code>
复制代码

以下代码创建 CORS 默认计谋和名为 "AnotherPolicy" 的计谋:

  1. public class StartupMultiPolicy
  2. {
  3. public StartupMultiPolicy(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. public IConfiguration Configuration { get; }
  8. public void ConfigureServices(IServiceCollection services)
  9. {
  10. services.AddCors(options =>
  11. {
  12. options.AddDefaultPolicy(
  13. builder =>
  14. {
  15. builder.WithOrigins("http://example.com",
  16. "http://www.contoso.com");
  17. });
  18. options.AddPolicy("AnotherPolicy",
  19. builder =>
  20. {
  21. builder.WithOrigins("http://www.contoso.com")
  22. .AllowAnyHeader()
  23. .AllowAnyMethod();
  24. });
  25. });
  26. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  27. }
  28. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  29. {
  30. if (env.IsDevelopment())
  31. {
  32. app.UseDeveloperExceptionPage();
  33. }
  34. else
  35. {
  36. app.UseHsts();
  37. }
  38. app.UseHttpsRedirection();
  39. app.UseMvc();
  40. }
  41. }
复制代码

禁用 CORS

@No__t-1DisableCors @ no__t-2属性对控制器/页模子/操纵禁用 CORS。

CORS 计谋选项

本部分先容可在 CORS 计谋中设置的各种选项:

Startup.ConfigureServices 中调用 AddPolicy。 对于某些选项,最好先阅读CORS 怎样工作部分。

设置答应的泉源

AllowAnyOrigin – 答应全部泉源的 CORS 哀求和任何方案(httphttps)。 AllowAnyOrigin 不安全,因为任何网站都可以向应用程序发出跨域哀求。

备注

指定 @no__t 0 和 @no__t 为不安全设置,大概导致跨站点哀求伪造。 使用这两种方法设置应用时,CORS 服务将返回无效的 CORS 响应。

AllowAnyOrigin 会影响预检哀求和 @no__t 标头。 有关详细信息,请参阅预检哀求部分。

SetIsOriginAllowedToAllowWildcardSubdomains – 将计谋的 @no__t 设置为在评估是否答应源时答应源与设置的通配符域匹配的函数。

  1. options.AddPolicy("AllowSubdomain",
  2. builder =>
  3. {
  4. builder.WithOrigins("https://*.example.com")
  5. .SetIsOriginAllowedToAllowWildcardSubdomains();
  6. });
复制代码

设置答应的 HTTP 方法

AllowAnyMethod

  • 答应任何 HTTP 方法:
  • 影响预检哀求和 @no__t 0 标头。 有关详细信息,请参阅预检哀求部分。

设置答应的哀求标头

若要答应在 CORS 哀求中发送特定标头(称为作者哀求标头),请调用 WithHeaders 并指定答应的标头:

  1. options.AddPolicy("AllowHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .WithHeaders(HeaderNames.ContentType, "x-custom-header");
  6. });
复制代码

  1. <code data-author-content="options.AddPolicy("AllowHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .WithHeaders(HeaderNames.ContentType, "x-custom-header");
  6. });
  7. "></code>
复制代码

若要答应全部作者哀求标头,请调用 AllowAnyHeader

  1. options.AddPolicy("AllowAllHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .AllowAnyHeader();
  6. });
复制代码
  1. <code data-author-content="options.AddPolicy("AllowAllHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .AllowAnyHeader();
  6. });
  7. "></code>
复制代码

此设置会影响预检哀求和 @no__t 0 标头。 有关详细信息,请参阅预检哀求部分。

仅当在 Access-Control-Request-Headers 中发送的标头与 WithHeaders 中指定的标头完全匹配时,才可以使用 CORS 中间件计谋与 WithHeaders 指定的特定标头匹配。

比方,思量按如下方式设置的应用:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
  1. <code data-author-content="app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
  2. ">
  3. </code>
复制代码

CORS 中间件使用以下哀求标头拒绝预检哀求,因为 WithHeaders 中未列出 Content-LanguageHeaderNames):

  1. <code data-author-content="Access-Control-Request-Headers: Cache-Control, Content-Language
  2. ">Access-Control-Request-Headers: Cache-Control, Content-Language
  3. </code>
复制代码

应用返回200 OK响应,但不会向后发送 CORS 标头。 因此,欣赏器不会实行跨域哀求。

设置公开的响应标头

默认环境下,欣赏器不会向应用程序公开全部的响应标头。 有关详细信息,请参阅W3C 跨域资源共享(术语):简单的响应标头

默认环境下可用的响应标头包罗:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS 规范将这些标头称为简单的响应标头。 若要使其他标头可用于应用程序,请调用 WithExposedHeaders

  1. options.AddPolicy("ExposeResponseHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .WithExposedHeaders("x-custom-header");
  6. });
复制代码

  1. <code data-author-content="options.AddPolicy("ExposeResponseHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .WithExposedHeaders("x-custom-header");
  6. });
  7. "></code>
复制代码

跨域哀求中的根据

根据需要在 CORS 哀求中举行特别处理惩罚。 默认环境下,欣赏器不会使用跨域哀求发送根据。 根据包罗 cookie 和 HTTP 身份验证方案。 若要使用跨域哀求发送根据,客户端必须将 XMLHttpRequest.withCredentials 设置为 true

直接使用 @no__t:

  1. var xhr = new XMLHttpRequest();
  2. xhr.open('get', 'https://www.example.com/api/test');
  3. xhr.withCredentials = true;
复制代码

使用 jQuery:

  1. $.ajax({
  2. type: 'get',
  3. url: 'https://www.example.com/api/test',
  4. xhrFields: {
  5. withCredentials: true
  6. }
  7. });
复制代码

使用提取 API

  1. fetch('https://www.example.com/api/test', {
  2. credentials: 'include'
  3. });
复制代码

服务器必须答应根据。 若要答应跨域根据,请调用 AllowCredentials

  1. options.AddPolicy("AllowCredentials",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .AllowCredentials();
  6. });
复制代码

HTTP 响应包罗一个 @no__t 0 的标头,该标头关照欣赏器服务器答应跨源哀求的根据。

如果欣赏器发送根据,但响应不包罗有效的 @no__t 0 标头,则欣赏器不会向应用程序公开响应,而且跨源哀求会失败。

答应跨域根据会带来安全风险。 另一个域中的网站可以代表用户将登任命户的根据发送给该应用程序,而无需用户的知识。

CORS 规范还指出,如果 @no__t 标头存在,则将源设置为 "*" (全部源)是无效的。

预检哀求

对于某些 CORS 哀求,欣赏器会在发出实际哀求之前发送其他哀求。 此哀求称为预检哀求。 如果满意以下条件,欣赏器可以跳过预检哀求:

  • 哀求方法为 GET、HEAD 或 POST。
  • 应用未设置 AcceptAccept-LanguageContent-LanguageContent-Type 或 @no__t 为的哀求标头。
  • @No__t 的标头(如果已设置)具有以下值之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

为客户端哀求设置的哀求标头上的规则实用于应用通过调用 @no__t @no__t 对象上的的标头。 CORS 规范调用这些标头作者哀求标头。 规则不实用于欣赏器可以设置的标头,如 User-AgentHostContent-Length

下面是预检哀求的示例:

  1. <code data-author-content="OPTIONS https://myservice.azurewebsites.net/api/test HTTP/1.1
  2. Accept: */*
  3. Origin: https://myclient.azurewebsites.net
  4. Access-Control-Request-Method: PUT
  5. Access-Control-Request-Headers: accept, x-my-custom-header
  6. Accept-Encoding: gzip, deflate
  7. User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
  8. Host: myservice.azurewebsites.net
  9. Content-Length: 0
  10. ">OPTIONS https://myservice.azurewebsites.net/api/test HTTP/1.1
  11. Accept: */*
  12. Origin: https://myclient.azurewebsites.net
  13. Access-Control-Request-Method: PUT
  14. Access-Control-Request-Headers: accept, x-my-custom-header
  15. Accept-Encoding: gzip, deflate
  16. User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
  17. Host: myservice.azurewebsites.net
  18. Content-Length: 0</code>
复制代码

预航班哀求使用 HTTP OPTIONS 方法。 它包罗两个特别标头:

  • Access-Control-Request-Method:将用于实际哀求的 HTTP 方法。
  • Access-Control-Request-Headers:应用在实际哀求上设置的哀求标头的列表。 如前文所述,这不包罗欣赏器设置的标头,如 User-Agent

CORS 预检哀求大概包罗一个 @no__t 0 标头,该标头向服务器指示与实际哀求一起发送的标头。

若要答应特定标头,请调用 WithHeaders

  1. options.AddPolicy("AllowHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .WithHeaders(HeaderNames.ContentType, "x-custom-header");
  6. });
复制代码

若要答应全部作者哀求标头,请调用 AllowAnyHeader

  1. options.AddPolicy("AllowAllHeaders",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .AllowAnyHeader();
  6. });
复制代码

欣赏器的设置方式并不完全划一 Access-Control-Request-Headers。 如果将标头设置为 @no__t 0 (或使用 AllowAnyHeader)以外的任何内容,则至少应包罗 AcceptContent-Type 和 @no__t,以及要支持的任何自界说标头。

下面是针对预检哀求的示例响应(假定服务器答应该哀求):

  1. <code data-author-content="HTTP/1.1 200 OK
  2. Cache-Control: no-cache
  3. Pragma: no-cache
  4. Content-Length: 0
  5. Access-Control-Allow-Origin: https://myclient.azurewebsites.net
  6. Access-Control-Allow-Headers: x-my-custom-header
  7. Access-Control-Allow-Methods: PUT
  8. Date: Wed, 20 May 2015 06:33:22 GMT
  9. ">HTTP/1.1 200 OK
  10. Cache-Control: no-cache
  11. Pragma: no-cache
  12. Content-Length: 0
  13. Access-Control-Allow-Origin: https://myclient.azurewebsites.net
  14. Access-Control-Allow-Headers: x-my-custom-header
  15. Access-Control-Allow-Methods: PUT
  16. Date: Wed, 20 May 2015 06:33:22 GMT
  17. </code>
复制代码

响应包罗一个 @no__t 0 标头,该标头列出了答应的方法,还可以选择一个 @no__t 标头,此中列出了答应的标头。 如果预检哀求乐成,则欣赏器发送实际哀求。

如果预检哀求被拒绝,应用将返回200 OK响应,但不会向后发送 CORS 标头。 因此,欣赏器不会实行跨域哀求。

设置预检逾期时间

@No__t 的标头指定可缓存对预检哀求的响应的时间长度。 若要设置此标头,请调用 SetPreflightMaxAge

  1. options.AddPolicy("SetPreflightExpiration",
  2. builder =>
  3. {
  4. builder.WithOrigins("http://example.com")
  5. .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
  6. });
复制代码

CORS 怎样工作

本部分先容 HTTP 消息级别的CORS哀求中发生的环境。

  • CORS不是一种安全功能。 CORS 是一种 W3C 标准,可让服务器放宽相同的源计谋。
    • 比方,恶意实行组件大概会对站点使用克制跨站点脚本(XSS) ,并对启用了 CORS 的站点实行跨站点哀求,以盗取信息。
  • API 不能通过答应 CORS 来更安全。
    • 它由客户端(欣赏器)来欺压实行 CORS。 服务器实行哀求并返反响应,这是返回错误并克制响应的客户端。 比方,以下任何工具都将体现服务器响应:
  • 这是一种方法,使服务器可以大概答应欣赏器实行跨源XHR获取 API哀求,否则将被克制。
    • 欣赏器(不含 CORS)不能实行跨域哀求。 在 CORS 之前,使用JSONP来绕过此限定。 JSONP 不使用 XHR,它使用
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则