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

如何基于JWT与Prisma实现登录用户的管理员权限验证

问题:实现管理员权限验证中间件

现有一个已正常运行的登录验证中间件AuthMiddleware,代码如下:

export const AuthMiddleware = (req: Request, res: Response, next: NextFunction) => {
    //Get the jwt token from the head
    const token = req.cookies.token
    let jwtPayload;
    try {
        jwtPayload = <any>jwt.verify(token, process.env.JWT_SECRET as string);
        res.locals.jwtPayload = jwtPayload;
    } catch (error) {
        res.status(401).send();
        return;
    }

    const { clientId, name } = jwtPayload;

    const newToken = jwt.sign({ clientId, name }, process.env.JWT_SECRET as string, {
        expiresIn: "1h"
    });
    res.setHeader("token", newToken);

    next();
};

对应的Prisma Client模型:

model Client {
  id         String          @id @default(uuid())
  email      String          @unique
  name       String
  password   String
  created_at DateTime        @default(now())
  updated_at DateTime        @updatedAt
  reviews    ProductReview[] @relation("client")
  adm        Boolean         @default(false) // 默认不是管理员,由首个管理员进行管理

  @@map("clients")
}

需要编写第二个中间件,检查当前登录用户的adm字段是否为true,验证其是否为管理员,该如何实现?


实现方案

编写管理员验证中间件

这个中间件必须在AuthMiddleware之后挂载,因为需要依赖登录验证后存在res.locals.jwtPayload中的clientId。实现代码如下:

import { Request, Response, NextFunction } from 'express';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export const AdminMiddleware = async (req: Request, res: Response, next: NextFunction) => {
    // 从登录中间件的上下文获取clientId
    const { clientId } = res.locals.jwtPayload;

    try {
        // 查询数据库中的用户信息,仅获取adm字段以减少数据传输
        const client = await prisma.client.findUnique({
            where: { id: clientId },
            select: { adm: true }
        });

        // 验证用户存在且具备管理员权限
        if (!client || !client.adm) {
            res.status(403).send('无管理员权限');
            return;
        }

        // 验证通过,执行后续路由逻辑
        next();
    } catch (error) {
        // 数据库查询异常返回服务器错误
        res.status(500).send('服务器内部错误');
        return;
    }
};

使用方式

在需要管理员权限的路由中,按顺序挂载两个中间件:

// 示例:管理员专属控制面板路由
router.get('/admin/dashboard', AuthMiddleware, AdminMiddleware, (req, res) => {
    res.send('管理员控制面板');
});

可选优化

  • 若想减少数据库查询次数,可在登录时将adm字段加入JWT Payload,但需注意:用户权限变更后需重新登录才会生效(JWT为无状态令牌)。
  • 将Prisma实例封装为全局单例,避免每次请求创建新实例。

内容的提问来源于stack exchange,提问作者Pedro Souza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:27:27