Express.js中JWT认证中间件出现Cannot set headers重复响应错误
解决JWT认证中间件的“Cannot set headers after they are sent to the client”错误
问题原因
你的代码存在两处核心问题,导致重复发送HTTP响应:
- 异步回调与外层响应冲突:
jwt.verify是异步方法,回调函数还未执行时,外层的return res.json(...)已经触发,同一请求会发送两次响应。 - 中间件越权发送响应:验证成功后,你先调用
res.json({ data: token_decode })发送响应,随后又调用next()让请求进入后续路由,后续路由若再发送响应就会触发“重复设置响应头”错误。中间件的职责是验证权限并传递上下文,而非直接返回业务响应。
修复后的代码
const jwt = require("jsonwebtoken"); const checkUserAuthentication = (req, res, next) => { const token = req.headers.token; // 无token直接返回错误 if (!token) { return res.json({ status: 0, msg: "Authorization failed: No token provided" }); } try { // 使用同步验证替代异步回调,避免执行顺序问题 const token_decode = jwt.verify(token.toString(), "secret"); // 将解码后的用户信息挂载到req对象,供后续路由使用 req.authUser = token_decode; // 放行请求到下一个中间件/路由 next(); } catch (err) { // 验证失败返回错误 return res.json({ status: 0, err: err.message, msg: "Authorization failed: Invalid token" }); } }; module.exports = checkUserAuthentication;
关键修改点
- 提前判断无token场景:直接返回错误并终止函数,避免进入后续逻辑。
- 改用同步验证逻辑:用
try/catch捕获验证错误,代码逻辑更线性,避免异步回调导致的响应冲突。 - 移除中间件内的业务响应:仅在验证失败时返回错误,验证成功后将用户信息挂载到
req,由后续路由处理响应。 - 确保单一出口:每个分支要么返回响应,要么调用
next(),避免重复发送响应。
内容的提问来源于stack exchange,提问作者Swapnil Mane
相关产品推荐
相关产品推荐

