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

关于动态路由和权限校验

  • vue-element-admin 将路由分为:constantRoutes 和 asyncRoutes 用户登录系统的时候会动态生成路由表

  • 用户登录系统时,会动态生成路由,其中 constantRoutes 必然包含,asyncRoutes 会进行过滤;

  • asyncRoutes 过滤的逻辑是看路由下是否包含 meta 和 meta.roles 属性,如果没有该属性,所以这是一个通用路由,不需要进行权限校验,会被加到路由表中;如果包含 roles 属性则会判断用户的角色是否命中路由中的任意一个权限,如果命中,则将路由保存下来,如果未命中,则直接将该路由舍弃;

  • asyncRoutes 处理完毕后,会和 constantRoutes 合并为一个新的路由对象,并保存到 vuex 的 permission/routes 中;

  • 用户登录系统后,侧边栏会从 vuex 中获取 state.permission.routes,根据该路由动态渲染用户菜单。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值