前端写好后本地预览接口一切正常,一上线控制台就红着脸:blocked by CORS policy,后面还跟着一句缺 Access-Control-Allow-Origin 头。这就是 cors failed,跟代码逻辑没关系,是浏览器在做同源检查。

为什么会触发跨域拦截

只要请求的协议、域名、端口三者有一个和当前页面不同,就算跨域。浏览器出于安全,会先发一个 OPTIONS 预检请求问服务器:让不让这个来源访问。服务器响应里没有正确的 CORS 头,预检不通过,真正的请求根本不会发出。注意是浏览器拦的,用 Node 或 curl 调试不受影响,这正是本地测着好好的原因。

服务端正确的响应头

Access-Control-Allow-Origin: https://a.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Credentials: true

关键点:Allow-Origin 不能随便写成星号再和 Credentials 一起用,带 Cookie 时必须写具体来源。带自定义头或非简单方法要配 Allow-Headers。OPTIONS 请求也要让后端返回 204,别被鉴权中间件拦掉。

常见框架怎么配

  • Spring Boot:用 @CrossOrigin 注解或 WebMvcConfigurer 的 addCorsMappings,注意别被全局拦截器覆盖。
  • Nginx:add_header 加头部,但要留意 add_header 在 4xx 时默认不生效,得补 always 参数。
  • Node Express:装 cors 中间件,app.use 里挂一行顶用,复杂场景再传 origin 白名单。

前后端别互相甩锅

很多团队卡在这里一天,后端说接口能通,前端说浏览器拦的。其实两边都没说谎:用 Postman 测不跨域当然通,问题就在响应头。最省事的做法是本地开发用 Vite 或 webpack 的 devServer.proxy 代理到后端,从源头绕开跨域。

  • 提醒:上生产别图省事把 Allow-Origin 设成星号又不校验来源,那等于把接口对全网开放,能配白名单就配。