You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 07:17:13