Next.js中间件调用数据库获取用户角色返回undefined问题
解决Next.js Middleware中获取用户角色返回undefined的问题
问题描述
在Next.js的middleware.ts中,我通过NextAuth完成身份验证后能成功获取用户邮箱,但调用自定义的getUserRoleByEmail方法时,返回的user结果为undefined,无法完成管理员权限校验。
相关代码
获取用户角色的函数
export const getUserRoleByEmail = async (email: string) => { try { const user = await db.user.findFirst({ where: { email }, select: { role: true } }); return user; } catch { return null; } };
Middleware代码
//middleware.ts import NextAuth from "next-auth"; import authConfig from "@/auth.config"; import { DEFAULT_LOGIN_REDIRECT, adminRoutes, apiAuthPrefix, authRoutes, publicRoutes, } from "@/routes"; import { getUserRoleByEmail } from "./data/user"; const { auth } = NextAuth(authConfig); //@ts-ignore export default auth(async (req) => { const { nextUrl } = req; const isLoggedIn = !!req.auth; const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix); const isPublicRoute = publicRoutes.includes(nextUrl.pathname); const isAuthRoute = authRoutes.includes(nextUrl.pathname); const isAdminRoute = adminRoutes.includes(nextUrl.pathname); if (isApiAuthRoute) { return null; } if (isAuthRoute) { if (isLoggedIn) { return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl)) } return null; } if (!isLoggedIn && !isPublicRoute) { return Response.redirect(new URL("/auth/login", nextUrl)); } const email = req.auth?.user?.email!; //trying to get the role const user = await getUserRoleByEmail(email) if (isAdminRoute && email !== process.env.ADMIN_EMAIL && user?.role !== "ADMIN") { return Response.redirect(new URL("/auth/login-as-admin", nextUrl)); } return null; }) // Optionally, don't invoke Middleware on some paths export const config = { matcher: ['/((?!.+\.[\w]+$|_next).*)', '/', '/(api|trpc)(.*)'], }
排查与解决步骤
1. 检查getUserRoleByEmail函数有效性
- 验证数据库连接:确认
db实例在Middleware的Edge Runtime环境下能正常访问数据库(比如Prisma需适配Edge环境,需导入@prisma/client/edge而非默认包)。 - 添加错误日志:修改函数的catch块,打印具体错误信息,定位查询失败原因:
export const getUserRoleByEmail = async (email: string) => { try { const user = await db.user.findFirst({ where: { email }, select: { role: true } }); return user; } catch (error) { console.error('获取用户角色失败:', error); return null; } }; - 直接验证数据库查询:手动执行SQL语句
SELECT role FROM user WHERE email = '你的测试邮箱',确认数据库中存在该邮箱的用户且role字段有值。
2. 修正Middleware中的参数处理
- 移除强制非空断言:原代码中
const email = req.auth?.user?.email!;的!会强制断言邮箱非空,若实际req.auth?.user?.email为undefined,会传入无效参数导致查询失败,改为:const email = req.auth?.user?.email; if (!email) { return Response.redirect(new URL("/auth/login", nextUrl)); } const user = await getUserRoleByEmail(email); - 确认
req.auth数据正确性:在获取邮箱前打印req.auth,确认user.email确实存在且格式正确。
3. 优化权限校验逻辑
当user为null或undefined时,当前逻辑会直接判定用户非管理员,可调整逻辑更严谨:
if (isAdminRoute) { if (email === process.env.ADMIN_EMAIL) { return null; } if (!user || user.role !== "ADMIN") { return Response.redirect(new URL("/auth/login-as-admin", nextUrl)); } }
内容的提问来源于stack exchange,提问作者Shyam Raghuwanshi
相关产品推荐
相关产品推荐

