JWT鉴权中间件抛错致Node.js服务崩溃,Postman无正常响应
问题:JWT认证中间件触发服务崩溃,无Token请求返回ECONNRESET
我基于JWT开发用户认证与受保护路由,编写了authMiddleware用于在无Token时返回未授权错误。但用Postman测试无Token请求时,Postman显示:
Could not get response
Error: read ECONNRESET
同时Node.js服务直接崩溃,控制台报错:
throw new Error("Not authorized");
^
Error: Not authorized at protect (file:///C:/Users/Suleyman/Desktop/converter/server/middleware/authMiddleware.js:26:13)
服务崩溃后需重启,虽已配置错误中间件,但问题仍存在。相关代码如下:
认证中间件(authMiddleware.js)
import User from '../models/userModel.js'; export const protect = async (req, res, next) => { let token; if ( req.headers.authorization && req.headers.authorization.startsWith("Bearer") ) { try { // 从请求头获取Token token = req.headers.authorization.split(" ")[1]; // 验证Token const decoded = jwt.verify(token, process.env.JWT_SECRET); // 通过Token获取用户信息(排除密码) req.user = await User.findById(decoded.id).select("-password"); next(); } catch (error) { console.log(error); res.status(401); throw new Error("Not authorized"); } } if (!token) { res.status(401); throw new Error("Not authorized, no token"); } };
控制器文件(userController.js)
// 获取当前用户信息 export const getMe = (req,res) => { res.json({message:'user data'}) }
路由文件(userRoutes.js)
import { getMe, loginUser, registerUser } from "../controllers/userController.js"; import { protect } from "../middleware/authMiddleware.js"; const router = express.Router(); router.post("/register", registerUser); router.post("/login", loginUser); router.get("/me",protect, getMe); export default router;
问题原因
在Express异步中间件中直接throw new Error会触发未捕获的异常,导致服务崩溃。Express的错误处理机制依赖于通过next(error)传递错误,而非直接抛出。
修复方案
修改authMiddleware.js,将抛出错误改为通过next()传递,同时补上缺失的jwt导入:
import User from '../models/userModel.js'; import jwt from 'jsonwebtoken'; // 补上jwt导入 export const protect = async (req, res, next) => { let token; if ( req.headers.authorization && req.headers.authorization.startsWith("Bearer") ) { try { token = req.headers.authorization.split(" ")[1]; const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decoded.id).select("-password"); next(); } catch (error) { console.log(error); // 通过next传递错误给错误处理中间件 next(new Error("Not authorized")); } } if (!token) { // 同样用next传递无Token的错误 next(new Error("Not authorized, no token")); } };
同时确保错误处理中间件正确配置(需放在所有路由之后):
// 全局错误处理中间件(必须包含err, req, res, next四个参数) app.use((err, req, res, next) => { // 保留已设置的状态码,默认500 const statusCode = res.statusCode === 200 ? 500 : res.statusCode; res.status(statusCode); res.json({ message: err.message, // 生产环境隐藏栈信息 stack: process.env.NODE_ENV === 'production' ? null : err.stack }); });
关键注意点
- Express异步中间件的错误必须通过
next(error)传递,直接抛出会导致服务崩溃。 - 原代码缺失
jwt模块的导入,需补上避免额外错误。 - 错误处理中间件必须定义在所有路由之后,才能捕获全局错误。
内容的提问来源于stack exchange,提问作者Süleyman Eminbəyli
相关产品推荐
相关产品推荐

