Next.js中间件路由保护失效及无限循环问题求助
Next.js 中间件路由保护问题解答
问题场景
使用Next.js开发时,需通过中间件实现以下路由保护逻辑:
- Cookie中无
userToken时,禁止访问/profile等非公开页面,跳转至登录页 - Cookie中存在有效
userToken时,禁止访问/login、/register等登录注册页面,跳转至首页
开发过程中遇到两个问题:
- 未携带token直接访问
/profile时,中间件未拦截,可直接进入页面 - 修复路由匹配规则后,已登录用户访问
/login或/register时触发终端无限循环,修改判断逻辑后问题解决,但不确定写法是否规范
原问题分析
第一个问题:/profile未被拦截
原因是中间件的matcher配置未包含/profile路由,导致中间件不会对该路径触发逻辑,直接放行。
第二个问题:无限循环
原代码中判断逻辑为:
if (token && isPublicPage) { return NextResponse.redirect(new URL('/', req.nextUrl.href)); }
其中isPublicPage包含/、/login、/register、/signOutPage。当用户已登录(有token)访问/时,该条件成立,会重定向到/,而重定向后的请求仍会触发中间件,再次进入该判断,形成无限循环。
修正方案及规范说明
将判断逻辑从“拦截所有公开页面”改为“仅拦截登录注册页面”是规范且正确的,理由如下:
- 公开页面需区分两类:一类是仅未登录用户可访问(
/login、/register),另一类是所有用户均可访问(/、/signOutPage) - 仅对登录注册页面做已登录拦截,避免对首页等允许已登录用户访问的页面触发不必要的重定向,从根源上解决循环问题
另外,代码中还有两个细节优化点:
- Cookie获取方式:使用
req.cookies.get('userToken')?.value替代req.cookies.userToken,Next.js的RequestCookies是基于Map的结构,get()方法是官方推荐的取值方式,更严谨。 - matcher配置:确保包含所有需要中间件处理的路由(包括
/profile),避免遗漏拦截。
最终规范代码示例
import { NextResponse, NextRequest } from 'next/server'; export async function middleware(req) { try { const path = req.nextUrl.pathname; // 定义所有公开页面(含登录注册、首页、退出页) const isPublicPage = path === '/login' || path === '/register' || path === '/' || path === '/signOutPage'; // 定义仅未登录用户可访问的页面(登录、注册) const authOnlyPage = path === '/login' || path === '/register'; // 规范获取Cookie值 const token = req.cookies.get('userToken')?.value; // 未登录且访问非公开页面:跳转登录页 if (!token && !isPublicPage) { return NextResponse.redirect(new URL('/login', req.nextUrl.href)); } // 已登录且访问登录/注册页:跳转首页 if (token && authOnlyPage) { return NextResponse.redirect(new URL('/', req.nextUrl.href)); } return NextResponse.next(); } catch (error) { return NextResponse.error(); } } // 包含所有需要中间件处理的路由 export const config = { matcher: ['/', '/login', '/register', '/signOutPage', '/profile'], };
内容的提问来源于stack exchange,提问作者Peter Sivak
相关产品推荐
相关产品推荐

