发布于 2026-01-06 3 阅读
0

在 Vue 中创建身份验证导航守卫

在 Vue 中创建身份验证导航守卫

你已经搭建了登录页面和身份验证系统!所有用户在访问网站其他页面之前都会先进入登录页面。但是,如果他们只是在网址中输入了其他路径会发生什么呢?如果他们没有通过身份验证,还能访问网站吗?

😳 糟糕。这完全不安全。

我们真正想要的是确保无论用户尝试访问哪个页面,只要他们未通过身份验证,就始终跳转到登录页面。在 Vue 中,使用导航守卫 (Navigation Guardian) 是实现这一目标的绝佳方法。

每当网站用户尝试访问某个页面时,您都会收到通知。导航守卫允许您在此时引入逻辑检查。然后,您可以决定是否允许用户访问目标页面,或者是否必须将其重定向到其他页面。

布置

假设我们已经设置好了一个名为 的路由器router。如果您之前没有设置过,相关文档非常有用。

我们已经完成了线路连接和路由设置。接下来呢?

骷髅

首先,我们需要了解有多种导航守卫函数可供使用。在本例中,我们将使用beforeEach一种会在用户每次从一个页面导航到另一个页面时触发,并在页面渲染之前解析的函数。

我们将该函数与我们的程序连接起来router。我们向该函数传递三个参数:他们试图前往的路线to、他们到达的路线from以及next……

router.beforeEach((to, from, next) => {
})
Enter fullscreen mode Exit fullscreen mode

下一个

next实际上它是一个函数,而且非常有趣。next必须调用它才能解决我们的守卫问题。因此,每个逻辑路径都需要next以某种方式命中它。

打电话的方式有很多种next,但我只想指出三种。

  • next()这会将您引导至下一组逻辑。如果没有下一组逻辑,则确认导航并将用户发送到to

  • next(false)这将用户送回页面from并中止其尝试进行的导航。

  • next(<route>)这将用户重定向到您指定的任何位置。

我们将使用导航栏中的第一个和最后一个选项。

我们的逻辑

好的,现在我们需要确定在什么情况下将用户重定向到哪个页面。在本例中,我们希望检查用户是否已通过身份验证。但是,并非所有页面都需要身份验证。我们可以在路由元数据中定义这一点,以便确定是否需要进行身份验证检查。

const routes = [
  {
    path: '/',
    component: Home,
    meta: {
      requiresAuth: false,
    },
  }
]
Enter fullscreen mode Exit fullscreen mode

这意味着我们首先要考虑的是我们的to路线是否可行requiresAuth

如果成功,我们还有更多内容要编写。如果失败,我们已确定用户可以导航到该位置,因此我们将调用 ` next().`。在这种情况下,该调用之后不会再执行任何操作,因此 `.`next()将确认导航。

router.beforeEach((to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
  } else {
     next()
  }
})
Enter fullscreen mode Exit fullscreen mode

事实证明,即使不用 else 语句,直接用next()catch 语句捕获所有异常,也能正常工作。但是,这样做会在以后引发问题。

我们的检查

现在我们来添加最后一块拼图。如果requiresAuthtrue,那么我们需要检查用户是否已通过身份验证。

请注意,我们并未展示具体的实现方式isAuthenticated。这可以是多种情况。我们只是假设我们有办法进行检查。

如果用户已通过身份验证,我们需要确认导航操作。否则,我们将直接跳转到相应login页面。

router.beforeEach((to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    if (isAuthenticated()) {
      next()
    } else {
      next('/login')
    }
  } else {
    next()
  }
})
Enter fullscreen mode Exit fullscreen mode

小规模重构

说实话,下面的实现方式更简洁一些。无需调用next()两次,if/else逻辑也更简单。但不知为何,我一直不太喜欢检查 false 的情况,总觉得有点让人困惑。不过,其他人可能感觉不同,所以要知道这也是一种选择。

router.beforeEach((to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    if (!isAuthenticated()) {
       next('/login')
    }
  } else {
     next()
  }
})
Enter fullscreen mode Exit fullscreen mode

我的兔子洞

最初,我的代码是这样的。而且它运行起来也完全一样!但我始终不明白其中return的关键部分以及我需要它的原因。所以我想解释一下。

router.beforeEach((to, from, next) => {
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    if (isAuthenticated()) {
      next()
      return
    }
    next('/login')
  }
  next()
})
Enter fullscreen mode Exit fullscreen mode

你也可以写return next(),随你喜欢。

next()只有当管道中没有剩余的钩子时,才会确认导航。由于没有else语句,只有执行过程,所以next()没有确认任何内容,只是将你跳转到了“下一个”操作。

对于无需身份验证的记录来说,这无关紧要,因为您会被直接引导到最终next()页面。但对于已验证用户,他们最终总是会跳转到登录页面。因此,为了实现这一点,return需要添加一个参数。它可以阻止后续代码的执行,并确认导航。

感谢与 Vue 维护者 Eduardo(推特账号 posva)的交流,我想补充一点说明。next在导航守卫代码块的每个逻辑路径中,无论其形式如何,都只能出现一次 `<div>` 实例。如果能够多次调用它,将会导致错误和 bug。

结论

就这样!我们已经构建了一个导航守卫,用于检查所有页面的身份验证。导航守卫,以及vue-router一般来说,功能非常强大。你还可以做很多其他事情,也有很多其他方法可以实现它。查阅文档并亲自尝试一下吧!

如果您对 vue-router 感兴趣,想了解更多相关知识,我将于 10 月 22 日举办一场线上研讨会!点击此链接即可享受早鸟优惠价,优惠将于周一(10 月 14 日)截止。

文章来源:https://dev.to/laurieontech/creating-an-authentication-navigation-guard-in-vue-32jm