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

ASP.NET网站Ajax POST调用ASP.NET Core 6.0 Web API的CORS问题排查

ASP.NET网站POST请求API遇401未授权问题排查

问题描述

我有一个ASP.NET网站(非Web应用),使用jQuery 2.1.4向ASP.NET Core 6.0 Web API发起Ajax POST请求时返回401 Unauthorized错误,但向同一控制器的其他GET接口请求完全正常。初步怀疑这不是单纯的CORS问题,可能涉及认证配置或请求处理逻辑。

相关代码与配置

Ajax POST请求代码

function insertLNItemStorageRequirement() {
  var tempLNStorage = {
    TItem: storageTempReq.t_item,
    TSrq1: storageTempReq.t_srq1,
    TSrq2: storageTempReq.t_srq2,
    TSq27: storageTempReq.t_sq27,
    TStmp: storageTempReq.t_stmp,
    TRcdVers: 0,
    TRefcntd: 0,
    TRefcntu: 0,
  };

  $.ajax({
    type: "POST",
    url: commonAPIURL + "api/LN/InsertItemStorageRequirement",
    data: JSON.stringify(tempLNStorage),
    contentType: "application/json; charset=utf-8",
    //dataType: "json",
    xhrFields: { withCredentials: true },
    success: function (response) {},
    failure: function (response) {
      alert(response.responseText);
    },
    error: function (response) {
      alert(response.responseText);
    },
  });
}

Web API接口方法

[HttpPost("InsertItemStorageRequirement")]
[Produces(typeof(IActionResult))]
public IActionResult InsertItemStorageRequirement([FromBody] Ttccgs016424 itemStorageReq)
{
    Ttccgs016424 newItemStorageReq = _LN.Ttccgs016424s.FirstOrDefault(s => s.TItem == itemStorageReq.TItem);

    if (newItemStorageReq == null)
    {
        newItemStorageReq = new Ttccgs016424()
        {
            TItem = itemStorageReq.TItem,
            TSrq1 = itemStorageReq.TSrq1,
            TSrq2 = itemStorageReq.TSrq2,
            TSq27 = itemStorageReq.TSq27,
            TStmp = itemStorageReq.TStmp,
            TRcdVers = itemStorageReq.TRcdVers,
            TRefcntd = itemStorageReq.TRefcntd,
            TRefcntu = itemStorageReq.TRefcntu
        };

        try
        {
            _LN.Ttccgs016424s.Add(newItemStorageReq);
            _LN.SaveChanges();
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);  
        }

        return StatusCode(StatusCodes.Status201Created);
    }
    else
    {
        return StatusCode(StatusCodes.Status412PreconditionFailed, "Item Storage Requirement already exists.");
    }
}

API的CORS配置(Startup.cs)

已将请求源加入origins数组:

services.AddCors(setup => {
    setup.DefaultPolicyName = "open";
    setup.AddDefaultPolicy(p => {
        p.AllowAnyHeader();
        p.WithMethods("OPTIONS", "GET", "POST", "PUT", "DELETE");
        p.WithOrigins(origins);
        p.AllowCredentials();
     });
});

请求头与响应头

OPTIONS预检请求头

OPTIONS /api/LN/InsertItemStorageRequirement HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:31227
Origin: http://localhost:14612
Referer: http://localhost:14612/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36 Edg/128.0.0.0

响应头

HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Wed, 11 Sep 2024 23:43:25 GMT
Content-Length: 5995

已尝试操作与更新

  1. 修改Ajax请求,使用credentials: 'include'替代xhrFields.withCredentials: true,无效。
  2. 调整请求data格式为'{itemStorageReq: "' + JSON.stringify(tempLNStorage) + '"}',无效。
  3. 确认IIS已安装CORS模块。
  4. 调整中间件顺序,将app.UseCors("open")移至app.UseRouting()之后、app.UseAuthentication()之前:
app.UseRouting();

app.UseCors("open");

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

app.UseEndpoints(endpoints =>
{
        endpoints.MapControllers();
});
  1. 考虑到端点路由下CORS模块不会自动响应OPTIONS请求,计划添加如下预检处理方法,尚未验证:
[HttpOptions("InsertItemStorageRequirement")]
public IActionResult PreFlightRoute() {
       return NoContent();
}

排查建议

  • 检查认证中间件对OPTIONS请求的处理:GET请求成功说明认证通道正常,但OPTIONS预检请求触发401,可能是NTLM/Negotiate认证要求OPTIONS请求也携带凭证。可在ASP.NET Core认证配置中添加规则,允许OPTIONS请求跳过认证。
  • 禁用IIS CORS模块测试:同时启用ASP.NET Core CORS中间件和IIS CORS模块可能导致冲突,暂时禁用IIS的CORS模块,仅使用ASP.NET Core的配置验证是否解决问题。
  • 简化API接口测试:暂时移除[FromBody]参数,将接口改为直接返回200状态码,测试预检请求是否能通过,排除模型绑定错误导致的隐性拦截。
  • 验证CORS配置的准确性:确认请求Origin完全匹配WithOrigins中的值(包括端口、协议),AllowCredentials()与Ajax的withCredentials配置保持一致。
  • 启用详细日志排查:在API的appsettings.json中设置日志级别为Debug,查看OPTIONS请求的完整处理流程,确认是认证中间件拦截还是CORS中间件未正确响应。

内容的提问来源于stack exchange,提问作者ben.kansas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:14:52