在 Vue 中创建身份验证导航守卫
你已经搭建了登录页面和身份验证系统!所有用户在访问网站其他页面之前都会先进入登录页面。但是,如果他们只是在网址中输入了其他路径会发生什么呢?如果他们没有通过身份验证,还能访问网站吗?
😳 糟糕。这完全不安全。
我们真正想要的是确保无论用户尝试访问哪个页面,只要他们未通过身份验证,就始终跳转到登录页面。在 Vue 中,使用导航守卫 (Navigation Guardian) 是实现这一目标的绝佳方法。
每当网站用户尝试访问某个页面时,您都会收到通知。导航守卫允许您在此时引入逻辑检查。然后,您可以决定是否允许用户访问目标页面,或者是否必须将其重定向到其他页面。
布置
假设我们已经设置好了一个名为 的路由器router。如果您之前没有设置过,相关文档非常有用。
我们已经完成了线路连接和路由设置。接下来呢?
骷髅
首先,我们需要了解有多种导航守卫函数可供使用。在本例中,我们将使用beforeEach一种会在用户每次从一个页面导航到另一个页面时触发,并在页面渲染之前解析的函数。
我们将该函数与我们的程序连接起来router。我们向该函数传递三个参数:他们试图前往的路线to、他们到达的路线from以及next……
router.beforeEach((to, from, next) => {
})
下一个
next实际上它是一个函数,而且非常有趣。next必须调用它才能解决我们的守卫问题。因此,每个逻辑路径都需要next以某种方式命中它。
打电话的方式有很多种next,但我只想指出三种。
-
next()这会将您引导至下一组逻辑。如果没有下一组逻辑,则确认导航并将用户发送到to。 -
next(false)这将用户送回页面from并中止其尝试进行的导航。 -
next(<route>)这将用户重定向到您指定的任何位置。
我们将使用导航栏中的第一个和最后一个选项。
我们的逻辑
好的,现在我们需要确定在什么情况下将用户重定向到哪个页面。在本例中,我们希望检查用户是否已通过身份验证。但是,并非所有页面都需要身份验证。我们可以在路由元数据中定义这一点,以便确定是否需要进行身份验证检查。
const routes = [
{
path: '/',
component: Home,
meta: {
requiresAuth: false,
},
}
]
这意味着我们首先要考虑的是我们的to路线是否可行requiresAuth。
如果成功,我们还有更多内容要编写。如果失败,我们已确定用户可以导航到该位置,因此我们将调用 ` next().`。在这种情况下,该调用之后不会再执行任何操作,因此 `.`next()将确认导航。
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
} else {
next()
}
})
事实证明,即使不用 else 语句,直接用next()catch 语句捕获所有异常,也能正常工作。但是,这样做会在以后引发问题。
我们的检查
现在我们来添加最后一块拼图。如果requiresAuth是true,那么我们需要检查用户是否已通过身份验证。
请注意,我们并未展示具体的实现方式
isAuthenticated。这可以是多种情况。我们只是假设我们有办法进行检查。
如果用户已通过身份验证,我们需要确认导航操作。否则,我们将直接跳转到相应login页面。
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
if (isAuthenticated()) {
next()
} else {
next('/login')
}
} else {
next()
}
})
小规模重构
说实话,下面的实现方式更简洁一些。无需调用next()两次,if/else逻辑也更简单。但不知为何,我一直不太喜欢检查 false 的情况,总觉得有点让人困惑。不过,其他人可能感觉不同,所以要知道这也是一种选择。
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
if (!isAuthenticated()) {
next('/login')
}
} else {
next()
}
})
我的兔子洞
最初,我的代码是这样的。而且它运行起来也完全一样!但我始终不明白其中return的关键部分以及我需要它的原因。所以我想解释一下。
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
if (isAuthenticated()) {
next()
return
}
next('/login')
}
next()
})
你也可以写return next(),随你喜欢。
next()只有当管道中没有剩余的钩子时,才会确认导航。由于没有else语句,只有执行过程,所以next()没有确认任何内容,只是将你跳转到了“下一个”操作。
对于无需身份验证的记录来说,这无关紧要,因为您会被直接引导到最终next()页面。但对于已验证用户,他们最终总是会跳转到登录页面。因此,为了实现这一点,return需要添加一个参数。它可以阻止后续代码的执行,并确认导航。
感谢与 Vue 维护者 Eduardo(推特账号 posva)的交流,我想补充一点说明。
next在导航守卫代码块的每个逻辑路径中,无论其形式如何,都只能出现一次 `<div>` 实例。如果能够多次调用它,将会导致错误和 bug。
结论
就这样!我们已经构建了一个导航守卫,用于检查所有页面的身份验证。导航守卫,以及vue-router一般来说,功能非常强大。你还可以做很多其他事情,也有很多其他方法可以实现它。查阅文档并亲自尝试一下吧!
文章来源:https://dev.to/laurieontech/creating-an-authentication-navigation-guard-in-vue-32jm如果您对 vue-router 感兴趣,想了解更多相关知识,我将于 10 月 22 日举办一场线上研讨会!点击此链接即可享受早鸟优惠价,优惠将于周一(10 月 14 日)截止。