.NET Core 允许跨域的两种方式实现(IIS 配置、C# 代码实现)
〇、前言
当把开发好的 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 设置为“*”(所有源)是无效的,如下图报错提示:

三、关于预检请求 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# 代码实现)的更多相关文章
- ajax处理跨域有几种方式
一.什么是跨域 同源策略是由Netscape提出的著名安全策略,是浏览器最核心.基本的安全功能,它限制了一个源(origin)中加载文本或者脚本与来自其他源(origin)中资源的交互方式,所谓的同源 ...
- php跨域的几种方式
PHP实现跨域的几种形式 1.JSONP(JSON with padding)原理 利用html里面script标签可以加载其他域下的js这一特性,使用script src的形式来获取其他域下的数据, ...
- SpringMVC解决跨域的两种方案
1. 什么是跨域 2. 跨域的应用情景 3. 通过注解的方式允许跨域 4. 通过配置文件的方式允许跨域 1. 什么是跨域 跨域,即跨站HTTP请求(Cross-site HTTP request),指 ...
- SpringBoot 中实现跨域的几种方式
一.为什么会出现跨域问题 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响. ...
- 跨域的两种解决方法jsonp和CORS
1.跨域 什么是跨域? 当你请求的url是不同源的数据的时候,浏览器一般会抛出请求跨域的错误,如下图: 造成跨域的原因? 即你违反了浏览器的同源策略的限制=>阻止一个域的js脚本和另外一个域的内 ...
- spring boot 解决 跨域 的两种方法 -- 前后端分离
1.前言 以前做项目 ,基本上是使用 MVC 模式 ,使得视图与模型绑定 ,前后端地址与端口都一样 , 但是现在有些需求 ,需要暴露给外网访问 ,那么这就出现了个跨域问题 ,与同源原则冲突, 造成访问 ...
- 深入浅出:了解jsonp跨域的九种方式
什么是“”跨域”: 跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容.由于安全原因,跨域访问是被各大浏览器所默认禁止的.当一个域与其他域建立了信 ...
- 跨域的几种方式以及call(),apply() bind()方法的作用和区别
jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议. 一个是描述信息的格式,一个是信息传递 ...
- ajax 跨域的几种方式
网络上跨域的文章大多一样,这里我写下,巩固下自己的知识,顺便做个记录 什么是跨域 这里简单拿百度的网址做个例子:http://www.baidu.com:80 (默认都是80端口.可省略) http ...
- Springboot设置跨域的三种方式
方式一(精细配置) 在需要跨域的整个Controller或者单个方法上添加@CrossOrigin注解 方式二(全局配置) @Configuration public class WebMvcConf ...
随机推荐
- [Java]算法练习:新农村建设
1 题目描述 from 网友 CASE1 输入 A1 A8 输出 [A1,A2,A3,A4,A5,A6,A7,A8] CASE2 输入 A1 K1 输出 [A1,B1,C1,D1,E1,F1,G1,H ...
- arc076f F - Exhausted?
ARC076 F - Exhausted? [题目大意] \(有m个座位,分别位于坐标为1,2,3,...,m的地方:n个客人,第i位客人只坐位于[0,li]∪[ri,m]的座位.每个座位只能坐一个人 ...
- Kubernetes学习之旅
# Kubernetes学习之旅 ## 引言 - 为什么选择Kubernetes- Kubernetes简介- Kubernetes的发展历程 ## Kubernetes基本概念 - 节点(Node) ...
- .NET CORE 部署到IIS上,HTTP 错误 500.19 - Internal Server Error
经排查,是因为项目中web.config的rewrite节点不支持,注释掉此节点即可,或者尝试下载相关依赖以支持此节点
- Python中的print()语句
Python中print()语句的相关使用 介绍 print()函数可以将输出的信息打印出来,即发送给标准输出流.Python中可以直接使用print()函数,将信息展示在控制台 基本使用方法 输出数 ...
- 看了绝对不会忘的 去中心化金融 - DeFi
DeFi Decentralized Finance, 去中心化金融,主要就是 以区块链技术为载体的金融模式. 注意:区块链是一种技术,而比特币是一种应用. Terminology fungible ...
- 机器学习04-(决策树、集合算法:AdaBoost模型、BBDT、随机森林、分类模型:逻辑回归)
机器学习04 机器学习-04 集合算法 AdaBoost模型(正向激励) 特征重要性 GBDT 自助聚合 随机森林 分类模型 什么问题属于分类问题? 逻辑回归 代码总结 波士顿房屋价格数据分析与房价预 ...
- 消息推送平台的实时数仓?!flink消费kafka消息入到hive
大家好,3y啊.好些天没更新了,并没有偷懒,只不过一直在安装环境,差点都想放弃了. 上一次比较大的更新是做了austin的预览地址,把企业微信的应用和机器人消息各种的消息类型和功能给完善了.上一篇文章 ...
- ssh终端工具推荐-WindTerm
什么是WindTerm 官方github https://github.com/kingToolbox/WindTerm A Quicker and better SSH/Telnet/Serial/ ...
- 文心一言 VS chatgpt (15)-- 算法导论3.2 4~5题
四.函数 $\lceil \lg n \rceil !$ 多项式有界吗?函数 $\lceil \lg \lg n \rceil !$ 多项式有界吗? 文心一言: chatgpt: 对于第一个问题,函数 ...