.NET Core 允许跨域的两种方式实现(IIS 配置、C# 代码实现)

net,core,允许,两种,方式,实现,iis,配置,c#,代码 · 浏览次数 : 1581

小编点评

**关于设置允许跨源域请求发送凭据 AllowCredentials()** *允许跨源请求发送凭据需要在 CORS 请求中进行特殊处理。 *若存在 Access-Control-Allow-Credentials 头,则将源 Origins 设置为“*”(所有源)是无效的。 **预检请求** *当使用适当的策略启用 CORS 时,ASP.NET Core 通常会自动响应 CORS 预检请求。 *但在某些情况下, 例如通过终结点路由使用 CORS,是不会自动响应的。 **设置预检 过时时间** *可以通过 .SetPreflightMaxAge() 来实现,如下代码: ```C# // 添加跨域策略services.AddCors(options => { options.AddPolicy("CorsPolicyName007", policy => { policy .WithOrigins("http://127.0.0.1:7000", "http://127.0.0.1:8000") .SetPreflightMaxAge(TimeSpan.FromHours(24)); }); }); ``` **设置预检过期时间** *可以通过 .SetPreflightMaxAge() 来实现,如下代码: ```C# // 添加跨域策略services.AddCors(options => { options.AddPolicy("CorsPolicyName007", policy => { policy .WithOrigins("http://127.0.0.1:7000", "http://127.0.0.1:8000") .SetPreflightMaxAge(TimeSpan.FromHours(24)); }); }); ```

正文

〇、前言

当把开发好的 WebApi 接口,部署到 Windows 服务器 IIS 后,postman 可以直接访问到接口并正确返回,这并不意味着任务完成,毕竟接口嘛是要有交互的,最常见的问题莫过于跨域了。

若前端文件是在当前接口文件下的 wwwroot 文件夹下,那么接口的访问就没问题,因为是同协议(http、https)、同地址(域名)、同端口,不存在跨域问题

但是,若前端和接口不是部署在一起的,那么一般都会存在跨域问题,本文将通过两种方式介绍如何使接口允许跨域请求。

一、IIS 配置实现

1、生效范围

如下图:

1 位置为 IIS 根目录,在此属性中配置“HTTP响应标头”时,作用域为“网站”下级目录中的全部应用。若后面修改了单个应用的 Headers,当更新应用文件后,修改会被还原。

2 位置是指定某一网站,在此属性中配置“HTTP响应标头”时,作用域为当前应用,不对其他同级应用有影响。需要注意的是,在项目文件夹更新后,单独配置的响应头信息将会消失。

  

2、常用的配置项共有四个

HTTP 响应标头 是否必含 解释
Access-Control-Allow-Origin * 或 http://IP:Port 允许跨域请求的地址,* 代表允许全部,若指定地址则仅支持填入一个
Access-Control-Allow-Headers Content-Type 当接口仅提供 Get 请求时,可省略;另外客户端添加的自定义请求头,需再次进行允许配置
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE 此处列出了全部常用的方法名,可根据需要可适当删除个别值
Access-Control-Allow-Credentials 默认为 false,可配置为 true 允许客户端携带验证信息,例如 cookie 之类的。为 true 时,不允许 Origin 设置为“*”

二、C# 代码实现

1、配置示例

主要是通过在 Startup.cs 文件中的 ConfigureServices() 方法添加跨域服务策略(services.AddCors()),然后在 Configure() 方法中将跨域策略加入到 HTTP 请求管道(HTTP request pipeline)中。

先列举一个实例,.Net 5.0 配置兼容预检请求,如下代码:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    // 添加跨域策略
    services.AddCors(options =>
    {
        // 配置默认策略和中间件:options.AddDefaultPolicy(policy =>{policy.WithOrigins("");});app.UseCors(); // 将自动应用于所有控制器终结点
        options.AddPolicy("CorsPolicyName0519", policy =>
        {
            policy
            //.AllowAnyOrigin() // AllowAnyOrigin 允许任何源地址的访问
            .WithOrigins("http://IP:Port") // 仅允许一个地址访问
            //.WithOrigins(new string[]{"http://IP1:Port1","http://IP2:Port2","http://IP3:Port3"}) // 支持同时允许多个指定地址的访问
            //.AllowAnyHeader() // 允许任何的Header头部标题
            .WithHeaders("Account", "ClientType", "OrgId", "Token", "Department", "EntAuthVebr") // 自定义请求头
            //.AllowAnyMethod() // 允许任何方法
            .WithMethods(HttpMethods.Options, HttpMethods.Get, HttpMethods.Post, HttpMethods.Put, HttpMethods.Delete) // 允许的谓词方法
            //.AllowCredentials() // 允许跨源请求发送凭据 允许时 Origin 不允许为“*”
            .SetPreflightMaxAge(TimeSpan.FromHours(24)); // 设置预检请求的最大缓存时间
        });
    });
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.UseCors("CorsPolicyName0519"); // 添加 CORS 中间件,允许跨域访问
    // ...
}

跨域请求策略可以同时配置多个。

使用 [EnableCors] 属性可以有针对性的启用同一个 CORS。也可以对需要 CORS 的终结点配置指定的策略名称,来实现最佳控制。

  • [EnableCors] 指定默认策略。
  • [EnableCors("{Policy String}")] 指定命名策略。

[EnableCors] 属性可应用于:控制器、控制器操作方法、Razor Page PageModel。

将 [EnableCors] 属性应用于控制器、操作方法或页面模型,并将中间件加入到管道来启用 CORS 时, 将这两种策略将同时生效。

与 [EnableCors] 相反的,[DisableCors] 属性标识禁用跨域策略。

通常,UseStaticFiles 在 之前 UseCors调用 。 使用 JavaScript 跨站点检索静态文件的应用必须在 UseStaticFiles 之前调用 UseCors。

2、关于 设置允许的发送请求的源地址 WithOrigins()

.AllowAnyOrigin:允许具有任何协议(http 或 https)的所有源的 CORS 请求。也就是说任何网站都可以向应用发出跨域请求,会导致跨网站请求伪造,因此并不安全。

.WithOrigins("http://IP1:Port1","http://IP2:Port2"):允许同时配置多个指定地址。(参数类型实际为:new string[]{ })

但是要配置具体的请求地址比较多时,全部通过 string[] 列出的话很不优雅,此时就需要通过通配符域来达到配置多地址的目的。

例如,当需求为允许多个地址(例如:*.example.com、https://*.example.net 同一后缀的多个域名通配符)时,就可以用到如下配置:

  SetIsOriginAllowedToAllowWildcardSubdomains:将策略的 IsOriginAllowed 属性设置为一个函数,当计算是否允许源时,此函数允许源匹配已配置的通配符域。

services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
        policy =>
        {
            policy
                .WithOrigins("https://*.example.com","https://*.example.net") // 等效于:new string[]{"地址1","地址2"}
                .SetIsOriginAllowedToAllowWildcardSubdomains();
        });
});

3、关于 设置允许的 HTTP 方法 WithMethods()

这个就没啥好说的了,需要那种就配置进去好了。

常用的就三种:Get、Post、Options。另外不常用的有六种:Put、Delete、Patch、Trace、Connect、Head。详见:HTTP 请求方法

4、关于设置允许的请求头 WithHeaders()

 .AllowAnyHeader():允许任何名称的 Header 属性。这种情况下,很容易出现非默认的请求头,导致触发预检请求 Options,影响系统性能,下文章节会着重介绍。

 .WithHeaders(HeaderNames.ContentType, HeaderNames.UserAgent):指定允许多个请求头。(参数类型实际为:new string[]{ })

当客户端需要添加指定的请求头,需要在 WithHeaders() 方法中全部配置上。

5、关于设置允许的响应头 WithExposedHeaders()

默认情况下,浏览器不会向应用公开所有响应头。默认可用的响应头包括:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。

.WithExposedHeaders(HeaderNames.Server,HeaderNames.Status):允许同时配置多个响应头。(参数类型实际为:new string[]{ })

6、设置允许跨源域请求发送凭据 AllowCredentials()

凭据需要在 CORS 请求中进行特殊处理。 默认情况下,浏览器不会使用跨源域请求发送凭据。 凭据包括 cookie 和 HTTP 身份验证方案。 要使用跨源请求发送凭据,客户端必须将 Credentials 设置为 true,默认情况下为 false。

.AllowCredentials():允许跨源请求发送凭据。

HTTP 响应包含一个 Access-Control-Allow-Credentials 头,它告诉浏览器服务器允许跨源请求的凭据。

如果浏览器发送凭据,但响应不包含有效的 Access-Control-Allow-Credentials 头,则浏览器不会向应用公开响应,而且跨源请求会失败。

允许跨源凭据会带来安全风险。另一个域中的网站可以在用户不知情的情况下代表用户将登录用户的凭据发送到应用。

CORS 规范还指出,如果存在 Access-Control-Allow-Credentials 头,则将源 Origins 设置为“*”(所有源)是无效的,如下图报错提示:

  

参考:https://learn.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-6.0#cors-with-named-policy-and-middleware

  https://learn.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-6.0#set-the-allowed-origins

 三、关于预检请求 Options

1、什么是预检请求?

“发送非简单跨域请求前的预检请求”,若该请求未正常返回,浏览器会阻止后续的请求发送。

注:Chrome 和 Microsoft Edge 浏览器不会在 F12 工具的 Network 选项卡上显示 OPTIONS 请求,需要额外配置,打开地址:chrome://flags/#out-of-blink-cors 或 edge://flags/#out-of-blink-cors,禁用,重启生效;Firefox 浏览器默认显示 OPTIONS 请求。

如下图,是一个预检请求的 headers 信息:

  

2、什么情况下会触发预检请求

预检请求(Options)属于实际请求(Get、Post 等)之外的操作,仅在部分情况下触发。

想达到不触发 Options 方法的目的,需同时满足下面三个条件:

  • 请求方法为 GET、POST 或 HEAD
  • 应用不会设置 Content-Type、Content-Language、Accept、Accept-Language 或 Last-Event-ID 以外的请求头
  • Content-Type 头(如果已设置)具有以下三个值之一:application/x-www-form-urlencoded、multipart/form-data、text/plain

预检请求可能包含以下 Headers:

  • Access-Control-Request-Method/Methods:将用于实际请求的 HTTP 方法。
  • Access-Control-Request-Headers:应用在实际请求上设置的请求头的列表。 如前文所述,这不包含浏览器设置的标头,如 User-Agent、Host、Content-Length 等。

如果预检请求被拒绝,应用将返回 200 OK 响应,但不会设置 CORS 头,浏览器后续也就不会尝试跨源请求。

3、预检请求的 [HttpOptions] 属性

当使用适当的策略启用 CORS 时,ASP.NET Core 通常会自动响应 CORS 预检请求。 但在某些情况下, 例如通过终结点路由使用 CORS,是不会自动响应的。

以下是官网给出的实例,分别是带参数的 Options 请求和不带参数两种:

详见官网:https://learn.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-6.0#tcer

[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
    // OPTIONS: api/TodoItems2/5
    [HttpOptions("{id}")]
    public IActionResult PreflightRoute(int id)
    {
        return NoContent();
    }
    // OPTIONS: api/TodoItems2 
    [HttpOptions]
    public IActionResult PreflightRoute()
    {
        return NoContent();
    }
}

4、设置预检过期时间 SetPreflightMaxAge()

Access-Control-Max-Age 头指定对预检请求的响应可以缓存多长时间。

此方法的目的是在第一次预检请求成功后,将预检结果缓存一段时间,从而避免重复的预检请求,提升应用性能。

代码配置跨域策略时,可通过 .SetPreflightMaxAge() 来实现,如下代码:

// 添加跨域策略
services.AddCors(options =>
{
    options.AddPolicy("CorsPolicyName007", policy =>
    {
        policy
        .WithOrigins("http://127.0.0.1:7000" , "http://127.0.0.1:8000" )
        .SetPreflightMaxAge(TimeSpan.FromHours(24)) // 设置预检请求的最大缓存时间
        ;
    });
});

参考:https://learn.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-6.0#tcer

与.NET Core 允许跨域的两种方式实现(IIS 配置、C# 代码实现)相似的内容:

.NET Core 允许跨域的两种方式实现(IIS 配置、C# 代码实现)

本文例举了通过 IIS 配置和 C# 代码实现后端允许跨域配置,并介绍了代码实现相关的配置项。最后简单介绍了一下预检请求 Options。

.Net Core对于`RabbitMQ`封装分布式事件总线

首先我们需要了解到分布式事件总线是什么; 分布式事件总线是一种在分布式系统中提供事件通知、订阅和发布机制的技术。它允许多个组件或微服务之间的协作和通信,而无需直接耦合或了解彼此的实现细节。通过事件总线,组件或微服务可以通过发布或订阅事件来实现异步通信。 例如,当一个组件完成了某项任务并生成了一个事件

推荐十个优秀的ASP.NET Core第三方中间件,你用过几个?

ASP.NET Core 作为一个强大的、跨平台的、高性能的开源框架,为开发者提供了丰富的功能和灵活的扩展性。其中,中间件(Middleware)是 ASP.NET Core 架构中的核心组件之一,它负责处理 HTTP 请求和响应的管道,允许开发者在请求和响应之间插入自定义逻辑。随着 ASP.NET

Asp .Net Core 系列:集成 CAP + RabbitMQ + MySQL(含幂等性)

简介 官网:https://cap.dotnetcore.xyz/ CAP 是什么? 是一个 EventBus,同时也是一个在微服务或者 SOA 系统中解决分布式事务问题的一个框架。它有助于创建可扩展,可靠并且易于更改的微服务系统。 什么是 EventBus? 事件总线是一种机制,它允许不同的组件彼

NET9 AspnetCore将整合OpenAPI的文档生成功能而无需三方库

OpenAPI 规范是用于描述 HTTP API 的标准。该标准允许开发人员定义 API 的形状,这些 API 可以插入到客户端生成器、服务器生成器、测试工具、文档等中。尽管该标准具有普遍性和普遍性,但 ASP.NET Core 在框架内默认不提供对 OpenAPI 的支持。 当前 ASP.NET

异常过滤器—MVC中异常过滤器使用

## 一、什么是异常过滤器? 异常过滤器(**Exception Filters**)是 ASP.NET Core 中用于处理全局异常的机制。它们允许你在发生异常时捕获、处理和记录异常,并提供自定义的异常处理逻辑。异常过滤器在整个应用程序范围内生效,可以用于处理各种异常情况。用于实现常见的错误处理策

C#/.NET/.NET Core编程技巧练习集(学习,实践干货)

DotNet Exercises介绍 DotNetGuide专栏C#/.NET/.NET Core编程常用语法、算法、技巧、中间件、类库练习集,配套详细的文章教程讲解,助你快速掌握C#/.NET/.NET Core各种编程常用语法、算法、技巧、中间件、类库等等。 GitHub开源地址:https:/

C#/.NET/.NET Core优秀项目和框架2024年6月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。

C#/.NET/.NET Core拾遗补漏合集(24年6月更新)

前言 在这个快速发展的技术世界中,时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节,以帮助大家更全面地了解这些技术栈的特性和发展方向。 欢迎加入DotNetGuide技术社区交流群 GitHub

C#/.NET/.NET Core优秀项目和框架2024年5月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。