Express.js路由级别中间件未被调用问题排查
问题根因
中间件完全不触发的核心原因是中间件函数签名不符合Express的普通中间件规则:
- Express 约定,4个参数的函数
(error, req, res, next)会被识别为错误处理中间件,只有当前置流程调用next(错误对象)时才会触发执行 - 你写的
authMiddleware是要在正常请求链路中执行的鉴权中间件,错误地把error放在了第一个参数位置,Express直接将它判定为错误处理中间件,正常请求不会走到这个逻辑里,自然完全不生效。
附带的其他逻辑问题
除了核心的签名错误,代码里还有几个会导致运行异常的隐患:
admin.initializeApp()写在中间件内部,每次请求都会触发初始化,Firebase Admin重复初始化会直接抛错,这个方法应该在项目启动时全局调用一次- Token的
exp过期时间单位是秒,Date.now()返回值单位是毫秒,直接比较会导致所有合法Token都被判定为过期 - 当请求头没有携带
authorization字段时,代码既不返回401响应也不调用next(),会导致请求挂起直到超时 - Token校验失败的分支没有做请求终止处理,逻辑不闭环
修正方案
首先把admin.initializeApp()挪到项目入口文件(比如app.ts/index.ts),项目启动时执行一次即可,不要放在中间件里。
修正后的鉴权中间件代码:
import { Request, Response, NextFunction } from 'express'; // 提前在项目入口初始化好admin实例,不要在中间件里初始化 const authMiddleware = (req: Request, res: Response, next: NextFunction): void => { try { const authHeader = req.headers.authorization; if (!authHeader || authHeader.startsWith('Bearer ') === false) { res.status(401).json({ message: "Invalid token" }); return; } const token = authHeader.split(' ')[1]; getAuth() .verifyIdToken(token) .then((decodedToken) => { // 把秒级时间戳转成毫秒再和Date.now()比较 if (!decodedToken || decodedToken.exp * 1000 < Date.now()) { res.status(401).json({ message: "Invalid token" }); return; } // 可按需把解码后的用户信息挂载到req上供后续控制器使用 (req as any).user = decodedToken; next(); }) .catch(() => { res.status(401).json({ message: "Invalid token" }); }); } catch (error) { next(error); } }; export default authMiddleware;
路由定义部分不需要做修改,修正中间件签名后,POST/PUT/DELETE三个路由的鉴权逻辑就会正常介入请求流程。
内容的提问来源于stack exchange,提问作者andrey.shedko
相关产品推荐
相关产品推荐

