You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6 MVC带授权策略的HttpPost请求出现CORS错误

你遇到的问题核心是:POST请求因带自定义头或非简单Content-Type触发了预检OPTIONS请求,但服务端没正确返回CORS相关响应头;而GET属于浏览器定义的「简单请求」,不需要预检所以能正常执行。下面是针对性的排查和解决步骤:

排查与解决方案

1. 修正Program.cs中CORS中间件的位置与策略

ASP.NET Core中间件的顺序至关重要,UseCors必须放在UseRouting之后、UseAuthorization之前,同时要覆盖预检请求需要的所有规则:

var builder = WebApplication.CreateBuilder(args);

// 注册CORS策略
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAppOrigin", policy =>
    {
        // 替换成你的应用实际域名(比如http://your-iis-domain.com)
        policy.WithOrigins("http://your-app-domain.com")
              .AllowAnyMethod() // 允许所有HTTP方法(含OPTIONS)
              .AllowAnyHeader() // 允许所有请求头(覆盖自定义头导致的预检失败)
              .AllowCredentials(); // 登录后带Cookie的请求必须加这个
    });
});

builder.Services.AddControllersWithViews();
// 其他服务注册(比如Azure AD身份验证相关)

var app = builder.Build();

// 中间件顺序严格遵循以下顺序
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// 此处必须放在UseRouting之后、UseAuthorization之前
app.UseCors("AllowAppOrigin");

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

注意:如果前端fetch请求带了credentials: 'include'(Azure登录后需要携带Cookie),CORS策略必须加上.AllowCredentials(),同时前端fetch要配置该选项。

2. 确保OPTIONS请求完全交给ASP.NET Core处理(IIS配置)

IIS 8.5默认的Handler Mapping会拦截OPTIONS请求,导致ASP.NET Core根本接收不到预检请求,需做以下配置:

方式一:修改web.config

在<system.webServer>节点下添加/修改:

<handlers>
  <!-- 移除默认拦截OPTIONS的处理器 -->
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <!-- 让ASP.NET Core模块处理所有请求 -->
  <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\YourApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />

<!-- 不要手动添加Access-Control-Allow-Origin,避免和ASP.NET Core的CORS中间件冲突 -->
<httpProtocol>
  <customHeaders>
    <remove name="X-Powered-By" />
  </customHeaders>
</httpProtocol>

方式二:通过IIS管理器配置

打开IIS管理器,找到你的站点,进入Handler Mappings:

  • 删除OPTIONSVerbHandler和ExtensionlessUrlHandler-Integrated-4.0
  • 确认aspNetCore处理器的路径为*、动词为*,确保所有请求(含OPTIONS)都交给ASP.NET Core处理

3. 检查前端fetch请求的配置

如果POST请求带了自定义头(比如Authorization)或Content-Type为application/json,需确保fetch配置正确:

fetch('/YourController/YourAction', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    // 其他自定义请求头
  },
  credentials: 'include', // 携带登录Cookie必须加这个
  body: JSON.stringify(yourData)
})

注:application/json类型的请求会触发预检,服务端CORS策略必须允许该头(用.AllowAnyHeader()即可覆盖)。

4. 禁用IIS自带的CORS模块(若已安装)

如果你之前在IIS上安装了官方CORS模块,它会和ASP.NET Core的CORS中间件冲突,导致预检响应头被覆盖或缺失。可在IIS管理器中进入站点的CORS功能,选择Disable,或在web.config中移除相关配置。

5. 验证预检请求是否到达ASP.NET Core

在Program.cs中添加一个调试中间件,确认OPTIONS请求是否被服务端接收:

// 放在UseCors之前
app.Use(async (context, next) =>
{
    if (context.Request.Method == "OPTIONS")
    {
        // 打印日志,确认OPTIONS请求到达服务端
        Console.WriteLine("收到OPTIONS预检请求");
    }
    await next();
});

开启web.config中的stdoutLogEnabled="true",查看日志确认请求是否到达。如果没收到,说明IIS仍在拦截OPTIONS请求,需回到步骤2重新配置。


内容的提问来源于stack exchange,提问作者Francesco B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:05:31