Express路由verifyAdmin中间件未执行完直接调用getUsers问题
问题原因
/路由的管理员校验未生效直接进入控制器,核心是中间件传参和逻辑不匹配:
- 定义的
verifyToken仅接收req、res、next三个参数,但verifyAdmin、verifyUser调用时额外传入了第四个权限判断回调,verifyToken内部完全没有处理这个回调参数,jwt校验通过后会直接调用传入的第三个参数next——这个next指向的是路由栈的下一个处理器也就是getUsers,写在第四个参数位置的管理员身份判断逻辑根本不会执行。 - 附带逻辑错误:
verifyUser中权限校验失败时写的next(res.status(403).json(...))是错误用法,next仅接收错误对象作为参数,直接返回响应即可不需要传入next。 - 路由顺序隐患:当前路由先注册
GET /:id再注册GET /,Express按注册顺序匹配路由,请求/时存在被/:id规则误匹配的风险。
修复代码
1. 改造verifyToken中间件,支持自定义权限校验回调
import jwt from "jsonwebtoken"; const JWT_KEY = "jwt"; // 生产环境请将密钥存入环境变量,不要硬编码在代码中 export const verifyToken = (req, res, next, customAuthCheck) => { const token = req.cookies.access_token; if(!token) return res.status(401).json("You are not authenticated"); jwt.verify(token, JWT_KEY, (err, user)=>{ if(err) return res.status(403).json("Token is invalid"); req.user = user; // 存在自定义校验逻辑则执行,否则直接放行 customAuthCheck ? customAuthCheck() : next(); }) };
2. 修正verifyUser、verifyAdmin逻辑
export const verifyUser = (req, res, next) => { verifyToken(req, res, next, () => { if(req.user._id === req.params.id || req.user.isAdmin){ next(); }else{ return res.status(403).json("You are not allowed to access this."); } }) } export const verifyAdmin = (req, res, next) => { verifyToken(req, res, next, () => { if (req.user.isAdmin) { return next(); } else { return res.status(403).json("you are not admin"); } }); };
3. 调整路由注册顺序
将静态路径路由放到动态参数路由前面,避免匹配错误:
import express from "express"; import { updateUser, deleteUser, getUser, getUsers, } from "../controllers/user.js"; import { verifyAdmin, verifyUser,verifyToken } from "../middlewares/verifytoken.js"; const router = express.Router(); //GET ALL 静态路径放前面 router.get("/", verifyAdmin, getUsers); //UPDATE router.put("/:id", verifyUser, updateUser); //DELETE router.delete("/:id", verifyUser, deleteUser); //GET router.get("/:id", verifyUser, getUser); export default router;
内容的提问来源于stack exchange,提问作者Muhammad Umair
相关产品推荐
相关产品推荐

