前端路由拦截时如何防止无限重定向?
我在用 Vue Router 做登录权限控制,但一进页面就疯狂跳转到登录页,明显是陷入了死循环。我试过在 beforeEach 里判断 token,没 token 就 redirect 到 /login,但好像没处理好白名单路径。
比如访问 /login 的时候也触发了拦截,又重定向到自己,结果浏览器直接卡死。下面是我写的拦截逻辑:
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (!token && to.path !== '/login') {
next('/login')
} else {
next()
}
})
明明加了 to.path !== ‘/login’ 判断,怎么还是会无限重定向?是不是哪里漏了?
关键是要建立一个白名单,把所有不需要权限的路径都放进去。比如登录页、注册页、404页面之类的。可以这样改:
另外建议再加个判断,如果已经有token还访问/login的话,可以重定向到首页,避免登录成功后又跳回登录页:
这样应该就能解决无限重定向的问题了。调试的时候可以在控制台打印to.path看看路由变化,特别管用。
/login,但没考虑其他可能的白名单路径,比如/register、/reset-password这些,更关键的是——你没处理name为login的路由跳转!有些项目会用命名路由,比如
next({ name: 'login' }),这时候to.path是/login,但如果你用name跳转,to.path可能还是/login,但逻辑上你没拦住。更稳妥的做法是搞个白名单数组,把所有公开路由都列出来,包括 path 和 name:
顺带说一句,你原代码里
next('/login')之后没return,虽然能跑,但万一后面还有逻辑,容易出事,加个return更稳妥。还有个更偷懒的写法是直接判断
to.path === '/login'不够,得用!whiteList.includes(to.path)这种,主题里加个配置文件,后面加新页面也方便维护。