Next.js 在_app.js实现路由认证时无效Token触发无限重定向报错求助
循环重定向成因
该死循环由两个逻辑缺陷叠加导致,和跳转代码放置的分支位置无关,这也是为何将跳转逻辑移到else分支外部依然触发报错的核心原因:
- 无效Token的处理逻辑未做公开路由白名单判断。当带着无效Token被重定向到
/login后,加载登录页时会重新触发_app.js的全局getInitialProps,此时代码依然能从Cookie中读取到无效Token,再次进入校验失败分支,重复触发向/login的跳转。浏览器检测到页面在/login路径内反复发生302跳转,会直接抛出"重定向无法完成"的错误。 - 校验识别出无效Token时,未同步清理Cookie中残留的坏值。无Token场景下不会触发循环,是因为
/login路径下本身没有可读取的Token值;但残留的无效Token会在每次路由加载时被重新读取、反复校验失败,哪怕跳转到登录页也无法终止校验流程。
落地调整方案
按以下规则修正全局认证校验逻辑,即可彻底打断循环链路:
- 给重定向判断增加路由白名单拦截:只要当前路径属于
/login、/register这类公开可访问路由,无论Token状态如何,都直接跳过全局认证的重定向逻辑,不再触发跳转。 - 校验识别出无效Token时,第一时间清理Cookie中残留的Token值,避免后续路由加载反复读取坏值触发校验。
- 增加防自跳转判断:如果计算得出的目标重定向地址和当前访问路径完全一致,直接跳过跳转逻辑,避免无意义的重复触发。
- 将硬编码的受保护路由判断统一抽成数组维护,降低后续扩展路由的维护成本。
调整后的核心逻辑参考代码
// _app.js 中 getInitialProps 调整后 static async getInitialProps({ Component, ctx }) { const { token } = parseCookies(ctx) const currentPath = ctx.pathname // 公开路由白名单 const publicRoutes = ['/login', '/register'] // 受保护路由集合 const protectedRoutes = ['/account', '/dashboard'] let pageProps = {} if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx) } // 当前已在公开路由,直接返回跳过所有重定向判断 if (publicRoutes.includes(currentPath)) { return { pageProps } } // 非公开路由下执行认证校验 if (!token) { if (protectedRoutes.includes(currentPath)) { redirectUser(ctx, '/login') } } else { try { const verified = jwt.verify(token, process.env.JWT_SECRET) // 将解析出的用户信息注入页面props,供业务逻辑使用 pageProps.user = verified } catch(err) { console.error('Token校验失败:', err) // 分场景清理残留的无效Token if (ctx.req) { // 服务端场景清理响应中的Cookie ctx.res.setHeader('Set-Cookie', 'token=; Max-Age=0; path=/;') } else { // 客户端场景清理浏览器Cookie import('js-cookie').then(cookieModule => cookieModule.remove('token')) } // 执行跳转 redirectUser(ctx, '/login') } } return { pageProps } }
注意:服务端场景下执行完
writeHead触发302跳转后,需及时终止后续渲染流程,避免同时输出重定向头和页面渲染内容,引发请求异常。
内容的提问来源于stack exchange,提问作者nflauria
相关产品推荐
相关产品推荐

