如何基于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
相关产品推荐
相关产品推荐

