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

为何跨源资源共享(CORS)未在服务器端拦截请求?附场景验证

为什么CORS没有在服务器端拦截POST请求?

这是因为你的POST请求属于CORS简单请求,浏览器不会先发送OPTIONS预检请求,而是直接发送实际的POST请求。服务端会先执行你的Post()方法,之后才会通过CORS中间件检查源是否合法——当发现源不被允许时,服务端不会添加CORS允许的响应头,但此时控制器方法已经执行完毕了。

详细解释:

CORS请求分为两类:

  • 简单请求:满足以下全部条件的请求:

    • HTTP方法是GET、HEAD或POST
    • Content-Type仅限于application/x-www-form-urlencoded、multipart/form-data或text/plain
    • 没有自定义的HTTP请求头
      你的$.post调用默认使用application/x-www-form-urlencoded作为Content-Type,完全符合简单请求的标准。
  • 预检请求:不满足简单请求条件的请求,浏览器会先发送OPTIONS请求到服务端,询问是否允许跨源请求。服务端的CORS中间件会直接处理这个OPTIONS请求,如果源不被允许,会直接返回403,不会执行后续的控制器方法。

对于简单请求,浏览器的处理流程是:

  1. 直接发送实际的请求(比如你的POST)到服务端
  2. 服务端执行控制器方法
  3. 服务端通过CORS中间件检查请求源是否在允许列表中
  4. 如果源不被允许,服务端不会添加Access-Control-Allow-Origin等响应头
  5. 浏览器收到响应后,发现没有允许当前源的CORS头,就会触发fail回调,但此时服务端的方法已经执行过了。

验证一下:

你可以给Get()方法也加个断点,会发现点击GET按钮时,Get()同样会被执行,然后浏览器才会报错——因为GET也是简单请求,流程和POST完全一致。

如何让服务端在执行方法前拦截?

如果希望服务端在执行控制器方法前就拦截不符合CORS规则的请求,你需要让请求变成预检请求。最简单的方式是修改客户端的POST请求,设置Content-Type为application/json:

$('#sender-post').click(() => {
  $.ajax({
    url: "http://localhost:9000/weatherforecast",
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({}), // 需要传递JSON格式的参数
    success: () => {
      $('#content-post').text('done');
    },
    error: () => {
      $('#content-post').text('fail');
    }
  });
});

这样浏览器会先发送OPTIONS预检请求,服务端的CORS中间件会直接检查源是否允许(你的配置只允许http://localhost:5000),发现不匹配后直接返回403,不会执行Post()方法。

另外,顺便提一下:你的Startup中UseCors()的位置是正确的,但如果需要允许特定的HTTP方法或头,可以在策略中明确配置:

options.AddDefaultPolicy(policy =>
{
  policy.WithOrigins("http://localhost:5000")
        .WithMethods("GET", "POST"); // 明确指定允许的HTTP方法
});

内容的提问来源于stack exchange,提问作者jysummers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:52:39