如何在Next.js 13中间件中获取localStorage数据实现角色路由?
Next.js中间件实现基于角色的身份验证解决方案
问题根源很明确:Next.js的中间件运行在边缘服务器/服务端环境,根本无法访问浏览器的localStorage——这是浏览器专属的存储API,服务端代码拿不到。要解决这个问题,核心是把用户角色信息放到中间件能读取到的地方,最常用的方案是用HTTP Cookie。
步骤1:登录成功后将角色存入Cookie
登录接口返回用户角色后,除了存到Redux和localStorage,还要把角色写入Cookie,这样中间件就能读取到。
如果是在客户端处理登录逻辑:
// 登录成功后从接口获取角色 const userRole = await fetchUserRole(); // 你的接口调用逻辑 // 存到localStorage localStorage.setItem('userRole', userRole); // 写入Cookie,配置有效期、安全属性 document.cookie = `userRole=${userRole}; path=/; max-age=86400; ${process.env.NODE_ENV === 'production' ? 'secure; same-site=strict' : ''}`;
如果是在服务端(比如API路由)处理登录:
// app/api/login/route.ts import { cookies } from 'next/headers'; export async function POST(request: Request) { // 处理登录逻辑,获取用户角色 const userRole = 'admin'; // 示例值 // 设置Cookie cookies().set({ name: 'userRole', value: userRole, path: '/', maxAge: 86400, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', }); // 返回响应 return Response.json({ success: true }); }
步骤2:在中间件中读取Cookie并做角色校验
在middleware.ts(或middleware.js)里,通过request.cookies获取角色,然后根据路由规则做权限控制:
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const userRole = request.cookies.get('userRole')?.value; const { pathname } = request.nextUrl; // 示例规则:/admin 路径仅允许admin角色访问 if (pathname.startsWith('/admin') && userRole !== 'admin') { // 无权限时重定向到无权限页面或登录页 return NextResponse.redirect(new URL('/unauthorized', request.url)); } // 其他路由规则:比如/dashboard 需要user或admin角色 if (pathname.startsWith('/dashboard') && !['user', 'admin'].includes(userRole || '')) { return NextResponse.redirect(new URL('/login', request.url)); } // 权限通过,继续请求 return NextResponse.next(); } // 指定中间件生效的路由范围(按需调整) export const config = { matcher: ['/admin/:path*', '/dashboard/:path*', '/profile/:path*'], };
关键安全提醒
- 不要完全信任Cookie里的角色:Cookie可以被客户端篡改,所以生产环境中,中间件最好结合用户ID(存在另一个Cookie里),调用内部API或直接查询数据库,验证该用户的真实角色是否与Cookie中的一致。示例:
export async function middleware(request: NextRequest) { const userId = request.cookies.get('userId')?.value; const userRole = request.cookies.get('userRole')?.value; if (!userId || !userRole) { return NextResponse.redirect(new URL('/login', request.url)); } // 调用内部API验证角色合法性 const verifyRes = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/verify-role`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId, userRole }), cache: 'no-store', }); if (!verifyRes.ok) { return NextResponse.redirect(new URL('/unauthorized', request.url)); } return NextResponse.next(); } - Cookie安全配置:生产环境一定要开启
secure(仅HTTPS下传输)和same-site=strict,防止CSRF攻击;如果不需要客户端读取角色,可以加上httpOnly: true,避免XSS攻击窃取Cookie。
内容的提问来源于stack exchange,提问作者Vijay
相关产品推荐
相关产品推荐

