【精华】使用策略模式处理vue-router 登录鉴权
常规的路由鉴权
在前端的路由鉴权中,简单的鉴权会根据用户的登录状态可以控制路由的访问,比如常见的:
- 登录状态可访问的路由
- 未登录状态可访问的路由
他们在路由守卫中代码示意如下:
const routes = [
{
path: '/',
redirect: '/dashboard',
},
{
path: '/dashboard',
component: Dashboard,
},
{
path: '/profile',
component: Profile,
meta: {
requiresAuth: true
},
}
];
我们定义了一个路由数组,在路由的meta对象中增加了一个requiresAuth
表示这个路由必须登录才能访问。
// 添加导航守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = true; // 假设这里有一个表示用户登录状态的变量
// 如果路由需要鉴权
const isRequiresAuth = to.matched.some(r => r.meta.requiresAuth);
if(isRequiresAuth && !isAuthenticated) {
next({ path: "/login" });
return;
}
next();
});
这样如果用户没有登录,当他进入到需要登录的路由时会被重定向到登录页进行登录。
但是这个又有一个新的问题,当用户已经登录后,它还是可以直接访问登录页,这显然不合理。
完善的常规路由鉴权
const routes = [
{
path: '/login',
component: Login,
meta: {
guest: true
}
}
];
我们给只能未登录访问的路由增加一个guest
属性,然后再去路由守卫中增加一个条件判断:
// 添加导航守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = true; // 假设这里有一个表示用户登录状态的变量
// 如果路由需要鉴权
const isRequiresAuth = to.matched.some(r => r.meta.requiresAuth);
if(isRequiresAuth && !isAuthenticated) {
next({ path: "/login" });
return;
}
// 只能访客访问
const isGuest = to.matched.some(r => r.meta.guest);
if(isGuest && isAuthenticated) {
next({ path: "/" });
return;
}
next();
});
这样就更加完善了,当用户访问只能访客访问的路由时,会被重定向到首页。
现在一个基本的路由鉴权就是这样了,相信这也是大多数前端spa项目使用的方式。
新增的鉴权需求
在国内的环境中,常常要求邮箱注册的用户或者第三方账号登录的用户,必须绑定手机号,我们必然会在路由守卫中增加一条新的判断条件。
如果用户没有绑定手机号,可以进入/bind-phone
路由页,如果已经绑定了就不允许进入了。
const routes = [
{
path: '/bind-phone',
component: BindPhone,
meta: {
bindPhone: true
}
}
];
// 添加导航守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = true; // 假设这里有一个表示用户登录状态的变量
const isPhone = false; // 假设这里有一个表示用户是否绑定了手机号的变量
// 如果路由需要鉴权
const isRequiresAuth = to.matched.some(r => r.meta.requiresAuth);
if(isRequiresAuth && !isAuthenticated) {
next({ path: "/login" });
return;
}
// 只能访客访问
const isGuest = to.matched.some(r => r.meta.guest);
if(isGuest && isAuthenticated) {
next({ path: "/" });
return;
}
// 登录且没有绑定手机号
const isBindPhone = to.matched.some(r => r.meta.bindPhone);
if (isBindPhone) {
if (!isRequiresAuth) {
next({ path: "/login" });
return;
}
if (!isPhone) {
next({ path: "/bind-phone" });
return;
}
next({ path: "/" });
}
next();
});
这样写其实也可以满足需求,如果你对代码有要求,你会感觉两个地方非常难受,一个就是meta属性里面塞了一堆新增的属性,然后路由守卫中增加了非常多的条件判断语句,导致整个守卫代码变得非常庞大且复杂,如果再新增几个条件,简直不敢想象。
后面的人维护起来非常痛苦,它要阅读非常多了代码才能了解某个条件的意义。
这时,设计模式就显得非常重要,我们可以通过策略模式来优化守卫中的条件语句。
此处内容已隐藏回复后方可阅读。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
全部评论 3
阿达
Google Chrome MacOS嘻嘻嘻嘻
Google Chrome Windows 10王企鹅
Google Chrome Windows 10