跨域是浏览器同源策略限制,非代码错误;CORS是服务端通过响应头(如Access-Control-Allow-Origin)授权跨域请求,需区分开发与生产配置,避免滥用通配符或绕过安全机制。

跨域不是代码写错了,而是浏览器在替你守门——它只放行同源请求,其余一律拦截。CORS 是服务器开的“通行许可”,学它关键不在背头,而在理清“谁发请求、谁拦请求、谁放行、为什么这样放”。下面按真实学习路径分四块讲清楚。
先搞懂:什么是跨域,为什么它总报错
跨域由协议 + 域名 + 端口三者共同决定。只要其中任一不同,就算跨域:
- http://a.com → https://a.com(协议不同)→ 跨域
- http://a.com → http://api.a.com(子域名不同)→ 跨域
- http://a.com:3000 → http://a.com:8080(端口不同)→ 跨域
注意:请求其实发出去了,服务端也正常响应了,但浏览器在收到响应后主动丢弃——所以你看 Network 面板里有请求、有状态码 200,但 JS 拿不到数据,控制台只报 Failed to fetch 或 No 'Access-Control-Allow-Origin' header。
动手验证:用 fetch 写一个典型跨域失败案例
在本地 HTML 文件里写一段最简 fetch:
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('出错了:', err));
直接双击打开该 HTML,大概率失败——因为文件是 file:// 协议,而目标是 https://,协议不同即跨域。这不是后端问题,是浏览器规则。要真正测试 CORS,必须用本地服务器(如 live-server 或 http-server 启动),让页面走 http://localhost:xxxx 协议。
服务端配 CORS:从 * 到精准控制
CORS 配置全在服务端响应头里,前端 fetch 不用改一行。以 Express 为例:
- 最简起步:
app.use(cors())→ 自动加Access-Control-Allow-Origin: *,适合开发阶段 - 生产环境必须限定来源:
origin: 'https://your-frontend.com',不支持通配符 + 端口或带路径的 URL - 若前端带 Cookie 或 Authorization 头,需额外设:
credentials: true,且origin不能为*,必须写具体域名 - 复杂请求(如 PUT、DELETE、含自定义 Header)会触发 OPTIONS 预检,
cors()中间件已自动处理,无需手写路由
手动设置响应头也完全可行(比如不用中间件时):
res.setHeader('Access-Control-Allow-Origin', 'https://your-frontend.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
绕过与替代:什么时候不该用 CORS
CORS 是标准方案,但不是唯一解,要看场景:
-
开发阶段调试:用 Webpack/Vite 的 proxy 配置,把
/api请求代理到后端,让前端“以为”没跨域 - 纯前端静态页调第三方 API:若对方不支持 CORS(如某些老接口),可用 JSONP(仅限 GET)或后端中转(自己搭个轻量 Node 代理)
-
不需要浏览器参与的请求:Node.js 环境下用
axios或node-fetch直接请求,无同源策略限制
别为了“解决跨域”而强行改前端逻辑(比如删掉 Authorization 头),那是在绕安全,不是学 CORS。


















