ExpressJS登录鉴权密码验证报错及连接拒绝问题求助
问题描述
我用ExpressJS开发登录鉴权接口,输入错误用户名或密码时,Postman能收到响应,但终端抛出ERR_HTTP_HEADERS_SENT错误;第二次发起请求时,Postman返回“Error: connect ECONNREFUSED 127.0.0.1:5000”。附上代码和错误日志,求解决。
代码
const router = require("express").Router(); const User = require("../models/User"); const bcrypt = require("bcrypt"); //REGISTER router.post("/register", async (req, res) => { try { const salt = await bcrypt.genSalt(10); const hashedPass = await bcrypt.hash(req.body.password, salt); const newUser = new User({ username: req.body.username, email: req.body.email, password: hashedPass, }); const user = await newUser.save(); res.status(200).json(user); } catch (err) { res.status(500).json(err); } }); //LOGIN router.post("/login", async (req, res) => { try { const user = await User.findOne({ username: req.body.username }); !user && res.status(400).json("Wrong credentials"); const validate = await bcrypt.compare(req.body.password, user.password); !validate && res.status(400).json("Wrong credentials"); res.status(200).json(user); } catch (err) { res.status(500).json(err); } }); module.exports = router;
错误日志
node:internal/errors:465 ErrorCaptureStackTrace(err); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11) at ServerResponse.header (C:\Users\Rahmad Hidayat\Desktop\react-blog\api\node_modules\express\lib\response.js:794:10) at ServerResponse.send (C:\Users\Rahmad Hidayat\Desktop\react-blog\api\node_modules\express\lib\response.js:174:12) at ServerResponse.json (C:\Users\Rahmad Hidayat\Desktop\react-blog\api\node_modules\express\lib\response.js:278:15) at C:\Users\Rahmad Hidayat\Desktop\react-blog\api\routes\auth.js:35:21 { code: 'ERR_HTTP_HEADERS_SENT' } [nodemon] app crashed - waiting for file changes before starting...
解决方案
1. 问题根源
ERR_HTTP_HEADERS_SENT错误是因为单次请求中发送了多次响应。登录接口里,当用户不存在时,代码执行!user && res.status(400).json("Wrong credentials")发送了一次响应,但没有终止后续代码,继续执行到const validate = await bcrypt.compare(...)时,user为undefined,访问user.password会抛出错误,进入catch块再次发送500响应,导致重复设置响应头。
而第二次请求的ECONNREFUSED是因为错误导致Node进程崩溃,nodemon重启前服务器未运行,所以连接被拒绝。
2. 修复后的登录接口代码
router.post("/login", async (req, res) => { try { const user = await User.findOne({ username: req.body.username }); if (!user) { return res.status(400).json("Wrong credentials"); } const validate = await bcrypt.compare(req.body.password, user.password); if (!validate) { return res.status(400).json("Wrong credentials"); } res.status(200).json(user); } catch (err) { res.status(500).json(err); } });
3. 修复说明
- 使用
if (!user) { return res.send(...) }:当用户不存在时,发送响应后立即return终止后续代码执行,避免访问undefined的user.password引发错误,同时确保只发送一次响应。 - 密码验证失败时同样用
return终止流程,严格保证每个请求仅发送一次响应。
修改后不会再出现重复设置响应头的错误,Node进程也不会崩溃,后续请求能正常连接服务器。
内容的提问来源于stack exchange,提问作者Rahmat Hidayat
相关产品推荐
相关产品推荐

