CORS 请求中 Access-Control-Allow-Headers 到底该怎么配?

司马姗姗 阅读 39

我在前端用 fetch 发了个带自定义 header 的请求,比如 X-Custom-Token,但浏览器报错说这个 header 被 CORS 策略拦了。后端是用 Express 写的,我已经加了 Access-Control-Allow-Origin: *,但好像还不够?

查了文档说要加 Access-Control-Allow-Headers,但我试了下面这样还是不行:

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

是不是漏了什么?为什么浏览器还是报错说不允许这个 header?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
南宫春晖
我之前也碰到过这问题,挺常见的。你只加了 Access-Control-Allow-Headers: X-Custom-Token,但浏览器在发预检请求(OPTIONS)的时候,会把所有你实际请求里要带的自定义 header 都列出来,而你后端只允许了其中一个,其他没允许的就会被拦。

更关键的是,如果你用的是 fetch 并且设置了 headers 字段,哪怕只是加了一个自定义 header,浏览器都会先发一个 OPTIONS 预检请求,这时候后端必须正确响应这个 OPTIONS 请求,而且要返回所有你需要的 header。

你现在的中间件只处理了普通请求(比如 GET/POST),但没处理 OPTIONS 预检请求,所以浏览器压根没收到允许的 header 列表。

可以这样改:

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

// 处理预检请求,直接返回 204,不往下走
if (req.method === 'OPTIONS') {
return res.status(204).end();
}

next();
});


注意几点:

1. Access-Control-Allow-Headers 里要把你实际会用到的所有自定义 header 都列出来,比如 X-Custom-TokenContent-Type(如果你发 JSON 就需要)、Authorization(如果带 token)等等,一个都不能少。

2. 一定要处理 OPTIONS 请求,不然它卡在预检阶段就直接报错了,后端甚至不会走到你真正的路由逻辑。

3. 如果你用的是 cors 中间件,其实更省事,直接:

const cors = require('cors');

app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['X-Custom-Token', 'Content-Type', 'Authorization']
}));


我之前踩坑的时候就是漏了 Content-Type,以为只配自定义 header 就行,结果一发 JSON 就挂,后来发现浏览器默认会加 Content-Type: application/json,没允许它也会报 CORS 错。

你试试把 OPTIONS 处理加上,再把需要的 header 全塞进 Access-Control-Allow-Headers,应该就能通了。
点赞 1
2026-02-24 22:04