登录接口输错账号/密码时崩溃,报错Cannot set headers after they are sent to the client
登录接口崩溃问题排查与修复
问题根源
你的代码核心问题是错误响应发送后未终止函数执行,导致后续代码继续运行并重复发送HTTP响应,触发Cannot set headers after they are sent to the client错误:
- 当用户名不存在时,
!user && res.status(401).json(...)发送了401响应,但函数没有停止,接下来会尝试访问undefined的user.password,最终进入catch块再次发送500响应,造成重复响应。 - 当密码错误时,发送401响应后,后续生成token、发送200响应的代码依然会执行,导致两次响应冲突。
修复后的代码
// Authentication router.post("/login", async (req, res) => { try{ const user = await User.findOne({username: req.body.username}); // 用户名不存在时,发送响应后终止函数 if (!user) { return res.status(401).json("User not found."); } const hashedPassword = CryptoJs.AES.decrypt(user.password, process.env.SECRET); const originalPassword = hashedPassword.toString(CryptoJs.enc.Utf8); // 密码错误时,发送响应后终止函数 if (originalPassword !== req.body.password) { return res.status(401).json(`Incorrect username or password`); } const token = jwt.sign({ id: user.id, isAdmin: user.isAdmin, }, process.env.JWT_SECRET, { expiresIn: "3d" }); const {password, ...otherParams} = user._doc; res.status(200).json({...otherParams, token}); } catch(e) { res.status(500).json("ERROR ERROR ERROR " + e); } })
关键修改说明
- 用显式
if判断替换原来的短路逻辑(&&),并在发送错误响应后调用return,确保函数立即停止执行,彻底避免后续代码重复发送响应。 - 这种写法逻辑更清晰,也符合Node.js HTTP响应的规范:每个请求只能发送一次响应。
内容的提问来源于stack exchange,提问作者Hello World
相关产品推荐
相关产品推荐

