如何利用路由守卫实现鉴权
约 1247 字大约 4 分钟
2025-03-13
在 Vue 中进行路由鉴权可以使用 Vue Router 提供的导航守卫功能。
通过导航守卫,你可以在路由跳转前进行一些验证操作:例如检查用户是否有权限访问该路由、用户是否已登录。
在这里我们主要利用路由守卫钩子
和路由元信息meta
来实现,比如我们可以在需要鉴权的路由下边配置:
{
path: '/',
name: 'Home',
component: () => import('./views/Home.vue') // 需要鉴权的页面
meta: {
checkLognin: true,
requiresAuth: true,
authList: ['601-101-111', '601-101-111']
}
},
这里我们介绍一下三种路由守卫和对应的场景
1. 全局守卫
全局所有的路由都会运行该钩子,一般用于检查用户是否登录,session 会话是否过期等。
// 导航守卫
router.beforeEach((to, from, next) => {
// 检查用户是否登录
const isLogined = checkLogin()
if (to.name !== 'Login' && !isLogined) {
// 如果用户未登录且要访问的页面需要鉴权,则跳转到登录页面
next({ name: 'Login' })
} else {
// 否则,允许访问该路由
next()
}
})
// 鉴权函数示例
function isLogined() {
// 在这里进行具体的鉴权逻辑,例如判断用户是否登录或者是否具有访问权限
// 返回true表示已经鉴权,允许访问;
// 返回false表示未鉴权,需要进行登录或者跳转到其他页面
// 根据自己的业务逻辑进行鉴权判断
const isAuthenticated = ...
return isAuthenticated
}
2. 路由独享守卫
一般用来检查针对路由设置的某些权限,比如某个具体的角色,某个具体的权限等。
const router = new VueRouter({
routes: [
{
path: "/your-route",
component: YourComponent,
meta: {
authList: [60111, 60112, 60113],
},
beforeEnter: (to, from, next) => {
// 在路由跳转前,你可以从to对象中获取meta对象
const metaData = to.meta;
console.log(metaData.authList); // 输出: [ 60111, 60112, 60113 ]
// 假设有个getAuthInfo方法能让我们拿到用户的权限信息
const authInfo = getAuthInfo();
let checkedAuth = authInfo.every((auth) =>
metaData.authList.includes(auth)
);
if (checkedAuth) {
next(); // 确保调用next()来resolve这个钩子
} else {
next({ name: "401 Page" }); // 调到401 没权限页面
}
},
},
],
});
注意
需要注意的是:当使用父子 嵌套路由 时,同级别的子路由跳转不会触发该事件,需要将路由守卫beforeEnter
具体到被拦截的子路由 上
如下示例中的 beforeEnter
在 /user/list
和 /user/details
之间移动时不会被调用,因为它们共享相同的父级路由/user
。
如果我们直接将 beforeEnter
守卫放在 details
路由上,那么在这两个路由之间移动时就会被调用。
const routes = [
{
path: "/user",
beforeEnter() {
// ...
},
children: [
{ path: "list", component: UserList },
{ path: "details", component: UserDetails },
],
},
];
3. 组件内守卫
最后,你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)。
一般用来鉴定当前用户的权限,是够可以操作该组件或组件内的一部分,以及用户离开当前组件和路由的时候,提醒用户有信息尚未保存。
<script>
export default {
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径:
// 在 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。
// 而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
};
</script>
beforeRouteEnter
守卫 不能 访问 this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意 beforeRouteEnter
是支持给 next
传递回调的唯一守卫。对于 beforeRouteUpdate
和 beforeRouteLeave
来说,this
已经可用了,所以不支持 传递回调,因为没有必要了:
beforeRouteUpdate (to, from) {
// just use `this`
this.name = to.params.name
}
这个 离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false
来取消。
beforeRouteLeave (to, from) {
if (this.savedFlg) { // 组件内当用户修改了内容时,设置变量值为ture,用户提交后改为false
const answer = window.confirm('您还有内容未保存,确认要离开当前页面?')
if (!answer) return false
}
}
更新日志
e7112
-1于