大家好,我是小杨,一个做了6年前端的老司机。今天想和大家聊聊项目中经常遇到的权限控制问题,尤其是角色权限分配这个让很多新手头疼的话题。
为什么我们需要权限控制?
记得我刚入行时接手的第一个后台管理系统项目,所有页面和功能对所有用户开放,结果测试同事用普通账号把管理员功能玩了个遍...(捂脸)从那以后我就明白了:权限控制不是可选项,而是必选项。
权限设计的核心思路
1. 权限模型:RBAC
目前最主流的是RBAC(Role-Based Access Control) 模型,也就是基于角色的访问控制。简单来说就是:
- 用户关联角色
- 角色关联权限
- 权限决定你能干什么
就像游戏里的设定:
- 普通玩家:只能打怪
- 公会会长:可以踢人
- GM:为所欲为
2. 前端权限控制三板斧
在实际项目中,我们通常需要控制:
- 页面权限:能不能进入这个路由
- 操作权限:按钮/功能能不能用
- 内容权限:能看到哪些数据
代码实战:Vue中的权限实现
路由权限控制
首先我们定义路由时加上meta信息:
javascript
const routes = [
{
path: '/dashboard',
component: Dashboard,
meta: { requiredRoles: ['admin', 'editor'] }
},
{
path: '/user-manage',
component: UserManage,
meta: { requiredRoles: ['admin'] }
}
]
然后在路由守卫里做校验:
javascript
router.beforeEach((to, from, next) => {
const myRoles = store.getters.roles // 获取我的角色
if (to.meta.requiredRoles) {
if (myRoles.some(role => to.meta.requiredRoles.includes(role))) {
next()
} else {
next('/403') // 无权限页面
}
} else {
next()
}
})
按钮权限控制
我们可以封装一个权限指令:
javascript
// v-permission指令
Vue.directive('permission', {
inserted(el, binding, vnode) {
const { value } = binding
const myRoles = store.getters.roles
if (value && value instanceof Array) {
const hasPermission = myRoles.some(role => {
return value.includes(role)
})
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error('需要传入角色数组,例如v-permission="['admin']"')
}
}
})
使用起来很简单:
html
<button v-permission="['admin']">删除用户</button>
动态菜单实现
根据权限动态生成侧边栏菜单:
javascript
// 过滤有权限的路由
function filterRoutes(routes, roles) {
return routes.filter(route => {
if (route.meta && route.meta.requiredRoles) {
return roles.some(role => route.meta.requiredRoles.includes(role))
}
return true
})
}
// 在vuex中使用
const filteredRoutes = filterRoutes(asyncRoutes, myRoles)
router.addRoutes(filteredRoutes)
性能优化小技巧
- 按需加载权限数据:只在用户登录后获取权限信息
- 缓存权限校验结果:避免重复计算
- 服务端校验兜底:前端校验只是提高体验,关键操作必须服务端再校验
我踩过的坑
- 动态路由刷新丢失:解决方案是存到vuex并在刷新时重新addRoutes
- 权限变更不及时:可以在用户信息变更时主动更新权限数据
- 按钮权限颗粒度:不要过度控制,否则维护成本很高
总结
权限控制就像给系统穿上合身的衣服 - 不能太紧影响活动,也不能太松走光。找到适合项目的平衡点很重要。希望我的这些经验能帮你少走弯路!
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!