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

Express路由verifyAdmin中间件未执行完直接调用getUsers问题

问题原因

/路由的管理员校验未生效直接进入控制器,核心是中间件传参和逻辑不匹配:

  1. 定义的verifyToken仅接收req、res、next三个参数,但verifyAdmin、verifyUser调用时额外传入了第四个权限判断回调,verifyToken内部完全没有处理这个回调参数,jwt校验通过后会直接调用传入的第三个参数next——这个next指向的是路由栈的下一个处理器也就是getUsers,写在第四个参数位置的管理员身份判断逻辑根本不会执行。
  2. 附带逻辑错误:verifyUser中权限校验失败时写的next(res.status(403).json(...))是错误用法,next仅接收错误对象作为参数,直接返回响应即可不需要传入next。
  3. 路由顺序隐患:当前路由先注册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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:48:16