RBAC 是基于角色的访问控制 Role-Based Access Control
1. 菜单的控制
在登录请求中会得到权限数据, 这个需要后端返回数据的支持。
前端根据权限数据, 展示对应的菜单。
{
id: 2,
username: '管理员',
password: 'admin',
token: 'abcdefghijklmnopqrstuvwxyz'.split('').reverse().join(''),
rights: [{
id: 1,
authName: '一级菜单',
icon: 'icon-menu',
children: [{
id: 11,
authName: '一级项目1',
path: '/menu/one',
rights: ['view', 'edit', 'add', 'delete']
}, {
id: 11,
authName: '一级项目2',
path: '/menu/two',
rights: ['view', 'edit', 'add', 'delete']
}]
}
...
用户登录之后服务端返回一个数据,这个数据有菜单列表和token,我们把这个数据放入到vuex中,然后主页根据vuex中的数据进行菜单列表的渲染
问题: 刷新界面vuex数据消失,菜单栏消失
解决: 在vuex中的 mutations 将数据存储在 sessionStorage 中,并让其和 vuex 中的数据保持同步
退出的时候记得删除数据
sessionStorage.clear()
this.$router.push('/login')
window.location.reload()
2.界面的控制
如果用户没有登录, 手动在地址栏敲入管理界面的地址, 则需要跳转到登录界面
如果用户已经登录, 如果手动敲入非权限内的地址, 则需要跳转404 界面
1. 路由导航守卫
登录成功后,将token数据存储在sessionStorage中,判断是否登录
问题: 这样用户在登录之后就可以访问其他界面了,但如果用户A登录之后他只能访问a页面,他不能访问b页面,但是这时候他还是可以通过地址栏输入进入到b页面
解决: 当然我们也可以设置路由导航守卫,但是如果有多个页面,设置会非常不方便,并且对于用户A来说,它是不用访问b页面的,这时候我们何不对A不显示b页面,这个时候我们就用到了动态路由
2. 动态路由
登录之后,根据当前用户所拥有的的权限数据来动态添加所需要的路由
- 先定义好所有的路由规则
- 登录成功之后动态添加路由,注意这个
initDynamicRoutes
的方法需要暴露出去在登录后调用
问题: 如果我们重新刷新的话动态路由就会消失,动态路由是在登录成功之后才会调用的,刷新的时候并没有调用,所以动态路由没有添加上。
解决: 可以在app.vue中的created中调用添加动态路由的方法
3.按钮的控制
在某个菜单的界面中, 还得根据权限数据, 展示出可进行操作的按钮,比如删除, 修改, 增加
比如我们可以根据后端返回的数据right来判断用户有什么权限,如下图
添加自定义指令 控制按钮
4.请求和响应的控制
如果用户通过非常规操作, 比如通过浏览器调试工具将某些禁用的按钮变成启用状态, 此时发的请求也应该被前端所拦截
- 除了登录请求都得要带上token , 这样服务器才可以鉴别你的身份这块使用的就是asiox的请求拦截器设置
如果发出了非权限内的请求, 应该直接在前端范围内阻止, 虽然这个请求发到服务器也会被拒绝
非权限内的请求:比如a用户是不能够操作该页面的按钮的,但是他通过f12调试把按钮改为可点击,如果我们不对这个请求进行处理,那么这个请求就会发送出去
响应控制
得到了服务器返回的状态码401, 代表token 超时或者被篡改了,此时应该强制跳转到登录界面
小结
前端权限的实现之须要后端提供数据支持, 否则无法实现。
返回的权限数据的结构, 前后端需要沟通协商怎样的数据便用起来才最方便
- 菜单控制
- 权限的数据需要在多组件之间共享, 因此采用vuex
- 防止刷新界面, 权限数据丢失, 所以需要存在sessionStorage, 并目要保证两者的同步
- 界面控制
- 路由的导航守卫可以防止跳过登录界面
- 动态路由可以让不具备权限的界面的路由规则压根就不存在
- 按钮控制
- 路由规则中可以增加路由元数据meta
- 通过路由对象可以得到当前的路由规则以及存在此规则中的meta 数据
- 自定义指令可以很方便的实现按钮控制
- 请求和响应控制
- 请求拦截器和响应拦截器的使用
https://blog.csdn.net/weixin_44157964/article/details/108420759