cors预检options返回403主因是服务器未正确处理该方法:nginx需显式拦截并返回204及完整cors头;spring boot须全局启用options支持;django中间件顺序必须正确;后端须注册options路由并返回200/204。

HTML 本身无法处理 CORS 预检请求(OPTIONS)——它不参与、也不可控;所谓“HTML 实现”,本质是前端触发了预检,而真正要解决的是后端如何正确响应它。
为什么改个 Content-Type 就挂了
因为 Content-Type: application/json 不属于简单请求的三类合法值(text/plain / application/x-www-form-urlencoded / multipart/form-data),浏览器立刻判定为非简单请求,强制先发 OPTIONS。如果你的后端没监听该路径,或没返回 Access-Control-Allow-Headers: Content-Type,预检就失败,主请求压根不会发出。
- 你在 Network 面板里只看到一个红字
OPTIONS 404或500,fetch报错却是No 'Access-Control-Allow-Origin' header,其实后端连主请求的影子都没见到 - 常见触发点:
fetch('/api/user', { method: 'POST', headers: { 'Content-Type': 'application/json' } })、axios.post('/login', { token: 'xxx' })(默认带application/json)、任何带自定义 header 的请求(如'X-Auth-Token': 'abc')
Spring Boot 2.4+ 的 @CrossOrigin 为什么突然不生效
新版本默认把 OPTIONS 路径从 CORS 过滤链中剥离了。@CrossOrigin 只作用于实际接口路径(如 /api/delete),但预检请求打到的是同路径的 OPTIONS /api/delete,若没显式配置,就会返回 405 Method Not Allowed。
- 必须用配置类替代注解,注册
CorsConfigurationSource - 如果用了 Spring Security,必须在安全配置里显式调用
http.cors(),否则安全链会拦截预检请求 -
allowedOrigins必须写明确域名(如http://localhost:3000),不能漏协议和端口;带credentials: true时,严禁用通配符*
Nginx 怎么处理 OPTIONS 预检
Nginx 层可以加头,但必须条件判断:预检请求可能不带 Origin,直接无脑加头会出错。
- 必须用
if ($http_origin) { ... }判断再添加 CORS 头,否则对非跨域请求也加头,可能引发兼容问题 - 预检响应应返回
204 No Content,不是200;不要返回 body,避免某些客户端解析异常 - 需显式允许方法:
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; - 若前端带自定义 header(如
Authorization),必须在Access-Control-Allow-Headers中显式列出
最常被忽略的一点:预检成功 ≠ 请求成功。即使 OPTIONS 返回了所有正确的 Access-Control-Allow-* 头,若后续实际请求的 Origin 与预检时不同(比如前端代码动态改了 origin、代理层篡改了 header),或者后端在业务逻辑里又覆盖/清除了 CORS 头,依然会失败。调试时一定要比对两次请求的 Origin 和响应头是否完全一致。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











