vue-element-admin路由和权限校验源码分析
准备
新建一个路由
src/views/book/create.vue
router 配置
原始文件:
可以看到路由在实例化的时候是使用的constantRoutes(任何用户都享有这个功能),asyncRoutes(比如说图书管理只有管理员才能访问)异步组件并没有被加载进去,那么在哪个环节asyncRoutes被读取并加载呢?
如何控制只有管理员能访问而其他人不能访问呢?
那么我们就要把我们的图书路由加在asyncRoutes中
{
path: '/book',
component: Layout,
meta: { title: '图书管理', icon: 'documentation' },
// 先不要写children 要不然左侧出不来图书管理菜单
},
菜单里内容是空的 因为现在只加载了layout组件 怎么验证呢 可以下个vue chrome插件方便验证
appmain里面是没有任何内容的 因为我们还没有进一步进行嵌套
{
path: '/book',
component: Layout,
meta: { title: '图书管理', icon: 'documentation' },
redirect:'/book/create',
children:[
{
path: '/book/create',
component: ()=>import('@/views/book/create'),
meta: { title: '上传图书', icon: 'edit' },
}
]
},
现在我们可以给他加个roles 代表哪些角色可以访问这个菜单
roles:[“admin”]
这里报404错误是因为登录以后进入到了/book/create (因为我是在那个页面登出的)
进入主页还是能看到图书管理的,但是上传图书就看不到了
{
path: '/book',
component: Layout,
// 这样图书管理也看不到了
meta: { title: '图书管理', icon: 'documentation' ,roles:["admin"] },
redirect:'/book/create',
children:[
{
path: '/book/create',
component: ()=>import('@/views/book/create'),
meta: { title: '上传图书', icon: 'edit' ,roles:["admin"]},
}
]
},
但是admin就可以看到这个这个菜单
权限校验的实现逻辑准备
https://www.youbaobao.xyz/admin-docs/guide/extra/router.html
先看这个,符合这种情况的话会做什么呢 会把App.vue里的<router-view>
替换
在看另一种,不在白名单,会在登录之后重定向到后面的xxx路由当中 就是上面我贴的那个gif动图,本来在/book/create下的,然后登出再登录以后就会自动到/book/create 而不是dashboard
再来看看这边有token的情况
如果有token还访问login的话 就会重定向到/ 根路径(dashboard)
如果访问的是book/create就会获取用户角色,动态生成路由,并且做权限的校验和匹配,如果匹配到路由的时候,会通过replace模式来访问路由,如果在这个流程中任何一步发生异常就会进入异常处理逻辑(用try /catch编写的)异常处理有两部分 1 重置token 2 访问/login 就是又回到了登录页面 也就是说一旦发生异常就会回到登录页面
还有一个隐藏的逻辑 – 当访问的路由不存在的时候会直接访问到404页面(不是在路由处理实现的,是在路由配置当中实现的)
*表示匹配一切路由,当我们上面的路由匹配不到的时候会匹配到*路由 直接重定向到/404(技巧)
中后台路由常见的常见如下:
已获取 Token:
访问 /login:重定向到 /
访问 /login?redirect=/xxx:重定向到 /xxx
访问 /login 以外的路由:直接访问 /xxx
未获取 Token:
访问 /login:直接访问 /login
访问 /login 以外的路由:如访问 /dashboard,实际访问路径为 /login?redirect=%2Fdashboard,登录后会直接重定向 /dashboard
逻辑源码
进入permission
关于路由守卫官方文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
debugger一下代码
1
在没有token的情况下访问login页面
beforeEach是在渲染之前实现的
理解next方法
可以用/book/create来验证一下
访问的是/book/create 但实际转入到了登录页面 而且登录以后是跳到/book/create的
2
登录上去以后的流程
登录以后再访问/login: 重定向到dashboard
路径不是/login的话
如果存在用户的角色 那就直接访问到next当中
如果roles不存在(第一次登录roles不存在) 他会调接口
拿到用户角色以后 是一个数组 这个数据从哪儿来的呢 --mock/user.js
动态路由是怎么生成的? 后面再说 这个动态路由针对的对象是asyncRoutes 会把符合条件的路由加到路由表当中
把这个路由与原来的路由进行合并
然后根据路由表生成左侧的菜单栏
这些步骤都完成之后会做一个重定向
这个replace:true什么意思呢 从登录页面进去之后在回退之后不会退到login页面,为什么这样做呢 --不会往history额外增加一个新的记录,不会保存一个新的历史记录 回退之后就会直接回退到一个空白页面
还有个流程就是异常的情况
出现异常会调用user/resetToken 位于 store/modules/user
重要的动态路由
如果是admin的话就直接将asyncRoutes保存到vuex中 并且将两个路由合并
不是admin的时候,比如现在是editor 会遍历所有的routes,取出每个routes进行判断,循环遍历判断是否具有访问权限,如果有的话就会判断路由当中是否存在子路由,存在子路由会用迭代的方法再进行子路由的遍历,对子路由进行过滤,过滤完对children进行更新,把不符合条件的子路由全部剔除掉,判断完成后,把路由存入到一个新的数组中,把新的数组替换到asyncRoutes,
然后保存到vuex中,最后合并。
一个关键的方法:
action只有一个方法 就是我们要找的那个
包含admin:
所以在生成左侧侧边栏的时候是根据state.routes来的
如果不包含admin:
看一下这个方法的源码
判断是否具有权限的方法:hasPermission 进去看看
function hasPermission(roles, route) {
// 找路由下面是否具有meta 如果没写meta,或者是meta下面没有roles属性 直接返回true
// 那就意味着有权限(没有定义权限的时候就视为有权限)
if (route.meta && route.meta.roles) {
// 如果定义了meta并且meta下面包含roles 他会做个判断(some命中一条就是true)
// 对每一个进行检查,检查传入的roles与 route.meta.roles是否有包含关系
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
再回到原来的方法:
//如果有权限的话 会去找是否有children
那这时候就有可能a是有权限的 b是没有权限的
管理员界面:
editor界面:
至于说怎么做到的不显示图书管理,这个就是siderbar里面的逻辑了(只包含一项的话父级不显示)
接着往下走 再次进行判断 更新temp.children 更新完之后push到res 最后返回res
res返回之后,替换掉accessedRoutes 然后与admin一样,后面的方法再走一遍
总结
关于路由处理
- vue-element-admin 对所有访问的路由进行拦截;
- 访问路由时会从 Cookie 中获取 Token,判断 Token 是否存在:
- 如果 Token 存在,将根据用户角色生成动态路由,然后访问路由,生成对应的页面组件。这里有一个特例,即用户访问
/login
时会重定向至/
路由;/路由也会重定向到dashboard - 如果 Token 不存在(没有登录),则会判断路由是否在白名单中,如果在白名单中将直接访问,否则说明该路由需要登录才能访问,此时会将路由生成一个 redirect 参数传入 login 组件,实际访问的路由为:
/login?redirect=/xxx
登录之后会做一个重定向,重定向到xxx 重定向怎么实现的在10.13
- 如果 Token 存在,将根据用户角色生成动态路由,然后访问路由,生成对应的页面组件。这里有一个特例,即用户访问
关于动态路由和权限校验
-
vue-element-admin 将路由分为:constantRoutes 和 asyncRoutes 用户登录系统的时候会动态生成路由表
-
用户登录系统时,会动态生成路由,其中 constantRoutes 必然包含,asyncRoutes 会进行过滤;
-
asyncRoutes 过滤的逻辑是看路由下是否包含 meta 和 meta.roles 属性,如果没有该属性,所以这是一个通用路由,不需要进行权限校验,会被加到路由表中;如果包含 roles 属性则会判断用户的角色是否命中路由中的任意一个权限,如果命中,则将路由保存下来,如果未命中,则直接将该路由舍弃;
-
asyncRoutes 处理完毕后,会和 constantRoutes 合并为一个新的路由对象,并保存到 vuex 的 permission/routes 中;
-
用户登录系统后,侧边栏会从 vuex 中获取
state.permission.routes
,根据该路由动态渲染用户菜单。
更多推荐
所有评论(0)