CORS是浏览器实施的跨域安全限制机制而非解决方案;它定义允许跨域的条件,请求实际已发送至服务端但响应被拦截,预检请求需服务端正确返回对应响应头,Access-Control-Allow-Origin配置错误或不匹配将导致跨域失败。

CORS 本身不是跨域请求的解决方案,而是浏览器对跨域请求施加的安全限制机制;它不解决跨域,只定义“在什么条件下允许跨域”。
为什么 fetch 或 XMLHttpRequest 发送跨域请求会失败
浏览器在发起跨域请求(协议、域名、端口任一不同)时,会先检查目标服务器响应头中是否包含合法的 Access-Control-Allow-Origin。如果没有,或值不匹配当前源,就直接拦截响应体——控制台报错 Blocked by CORS policy,但请求其实已发到服务端(可查服务端日志确认)。
常见误解是“CORS 配置错了所以请求没发出去”,实际是:请求发了,响应被浏览器丢弃了。
- 预检请求(
OPTIONS)触发条件:非简单请求(如带Content-Type: application/json、自定义 header、PUT/DELETE方法) - 服务端必须正确响应预检请求,返回
204或200,且含Access-Control-Allow-Methods、Access-Control-Allow-Headers等头 - 前端无法绕过 CORS 限制(除非禁用浏览器安全策略,仅限本地调试)
Access-Control-Allow-Origin 的取值陷阱
这个响应头决定哪些源能读取响应内容。看似简单,但几个典型错误会导致白屏或静默失败:
立即学习“前端免费学习笔记(深入)”;
- 设为
*时,不能同时设置Access-Control-Allow-Credentials: true(否则浏览器拒绝) - 设为具体域名(如
https://a.com)时,必须精确匹配,不支持通配子域名(https://*.a.com不合法) - 开发环境常误写成
localhost:3000,漏掉协议(应为http://localhost:3000或https://localhost:3000) - 后端动态生成该头时,未校验
Origin请求头,导致反射型 CORS 漏洞(如直接 echoOrigin值)
前端能做的有限补救:代理、mode: 'no-cors'、JSONP 的适用边界
当无法修改服务端 CORS 配置时,前端只能换路径绕行,而非“修复” CORS:
- 开发阶段用 Webpack/Vite 代理(如
proxy: { '/api': { target: 'http://localhost:8000' } }),把请求变成同源 -
mode: 'no-cors'会让请求发出,但响应变成opaque类型——JavaScript 无法读取状态码、header 或 body,仅适用于埋点、图片上传等无需响应解析的场景 - JSONP 只支持
GET,且依赖服务端包裹回调函数,现代 API 几乎不再支持;强行伪造会触发Uncaught ReferenceError - Service Worker 也无法绕过 CORS,它只能拦截已通过 CORS 检查的请求
CORS 的核心复杂性在于它横跨前后端:前端控制请求发起方式,后端控制响应头策略,而浏览器执行裁决。最容易被忽略的是预检请求的完整链路——少一个响应头,或错一个大小写(如 access-control-allow-origin 小写无效),整个跨域流程就中断。调试时务必用 curl -I 或浏览器 Network 面板逐个核对响应头,而不是只看前端报错。



















