Access-Control-Allow-Origin 设置了还是跨域报错?

UP主~梓希 阅读 4

我在本地开发时用 fetch 请求后端接口,明明在响应头里加了 Access-Control-Allow-Origin: *,但浏览器还是报跨域错误,这是为啥?

后端是用 Node.js 写的,代码大概这样:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

前端请求带了自定义 header,比如 Authorization,是不是这个原因导致的?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
极客瑞芹
这个问题太经典了,我刚踩过这个坑。

你猜对了,就是 Authorization 这个自定义 header 惹的祸。当请求带了自定义 header 时,浏览器会先发一个 OPTIONS 预检请求,你的代码没处理这个预检,所以直接翻车。

问题出在两个地方。第一,你没有处理 OPTIONS 请求,预检请求过来时直接 next() 了,没给浏览器想要的响应。第二,你的 Allow-Headers 里只有 Content-Type,根本没有 Authorization,浏览器一看不认识这个 header,直接拦截。

改一下代码就行:

app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

// 关键:预检请求直接返回204
if (req.method === 'OPTIONS') {
return res.sendStatus(204);
}

next();
});


加完这几行就完事了。OPTIONS 请求来了直接返回 204,告诉浏览器"这个请求我允许了",然后浏览器才会乖乖发真正的请求。

还有个坑提醒一下,如果你之后要带 Cookie,Allow-Origin 就不能写星号了,得写成具体的域名,比如 http://localhost:3000,还要加 Access-Control-Allow-Credentials: true。星号和 Cookie 不能同时存在,这是规范定的,别问我为啥。
点赞 1
2026-03-01 21:22