用vue实现权限管理的案例,vue权限管理系统

  用vue实现权限管理的案例,vue权限管理系统

  权限是访问特定资源的权限。所谓权限控制,就是保证用户只能访问被分配的资源。本文主要介绍vue的权限管理知识,有需要的朋友可以参考一下。

  

目录

   Vue应该怎么做权限管理?首先,它是什么?二、如何做界面权限路由权限控制菜单权限方案一方案二按钮权限方案一方案二总结

  

vue要做权限管理该怎么做?

  

一、是什么

  权限是访问特定资源的权限。所谓权限控制,就是保证用户只能访问分配的资源。

  前端权限归根结底就是发起请求的权利,请求的发起可能通过以下两种形式触发

  页面加载触发器按钮点击页面上的触发器一般来说,所有的请求都是从前端路由或者视图触发的。

  所以可以从这两个方面入手,控制触发权限的来源,最终达到以下目的:

  路由方面,用户登录后只能看到自己有权访问的导航菜单和有权访问的路由地址。否则,他们将跳转到4xx提示页面视图。用户只能看到他们有权访问的内容和他们有权访问的控件。最后,添加请求控制作为最后一道防线。路由可能配置错误,按钮可能忘记添加权限。在这种情况下,可以对底层使用请求控制,未经授权的请求会在前端被拦截。

  

二、如何做

  前端权限控制可以分为四个方面:

  权限按钮权限菜单权限路由权限

  

接口权限

  目前接口的权限一般由jwt验证。如果失败,一般会返回401,跳转到登录页面重新登录。

  登录后,您获得令牌,保存它,并通过axios请求拦截器拦截它。每次你请求的时候,你脑子里都带着这个令牌。

  axios . interceptors . request . use(config={

  config . headers[ token ]=cookie . get( token )

  返回配置

  })

  axios . interceptors . response . use(RES={ },{response}={

  if(response . data . code==40099 response . data . code==40098){//token过期或错误

  router.push(/login )

  }

  })

  

路由权限控制

  方案一

  也就是说,所有的路由都被初始化,并在路由上标注相应的权限信息,每次路由跳转前都进行验证。

  const routerMap=[

  {

  路径:“/权限”,

  组件:布局,

  重定向:“/权限/索引”,

  alwaysShow: true,//将始终显示根菜单

  元:{

  标题:“许可”,

  图标:“锁定”,

  roles: [admin , editor] //您可以在根导航中设置角色

  },

  孩子:[{

  路径:“页面”,

  组件:()=import( @/views/permission/page ),

  名称:页面权限,

  元:{

  标题:页面权限,

  roles: [admin] //或者您只能在子导航中设置角色

  }

  }, {

  路径:“指令”,

  component:()=import( @/views/permission/directive ),

  名称: directivePermission ,

  元:{

  标题:“直接许可”

  //如果不设置角色,意味着:此页面不需要权限

  }

  }]

  }]

  这种方法有以下四个缺点:

  加载所有路由,如果有许多路由,并且用户没有访问所有路由的权限,将会影响性能。在全局路由守护中,每个路由跳转都要进行权限判断。菜单信息写在前端。要更改显示文本或权限信息,您需要重新编译菜单并将其与路由耦合。定义路线时,还需要添加菜单显示标题和图标等信息。而且路线不一定显示为菜单,需要添加更多字段来标记方案二

  初始化时,先挂载不需要权限控制的路由,比如登录页、404等错误页。如果用户通过URL进行强制访问,会直接进入404,相当于从源头上进行控制。

  登录后获取用户的权限信息,然后筛选有权限访问的路由,调用全局路由卫士中的addRoutes添加路由。

  从导入路由器。/路由器

  从导入存储。/商店

  从"元素-用户界面"导入{消息}

  从" NProgress"//进度条导入进步

  导入“n进步/n进步。CSS"//进度条样式

  从甜饼干中的" @/utils/auth"//getToken导入getToken

  进步。配置({ show spinner:false })//n进度配置

  //权限判断函数

  函数具有权限(角色,权限角色){

  if (roles.indexOf(admin)=0)返回true //直接传递的管理权限

  如果(!权限角色)返回真实的

  回归角色。一些(角色=权限角色。(角色的索引)=0)

  }

  常数白名单=[/login ,/authredirect]//无重定向白名单

  router.beforeEach(收件人,发件人,下一个)={

  NProgress.start() //启动进度条

  if (getToken()) { //确定是否有令牌

  /*有标记*/

  if (to.path===/login) {

  下一步({路径:/ })

  NProgress.done() //如果当前页面是仪表盘就不会触发伸手可及之后钩子,所以手动处理它

  }否则{

  如果(存储。吸气剂。角色。长度===0){//判断当前用户是否已拉取完用户信息信息

  store.dispatch(GetUserInfo ).然后(res={ //拉取用户信息

  const roles=res.data.roles //注意:角色必须是数组!如:[编辑,开发]

  store.dispatch(GenerateRoutes ,{ roles }).然后(()={ //根据角色权限生成可访问的路由表

  路由器。添加路线(商店。吸气剂。添加路由器)//动态添加可访问路由表

  下一个({.to,replace: true }) //hack方法确保添加路线已完成,设置替换:真,这样导航就不会留下历史记录

  })

  }).catch((err)={

  store.dispatch(FedLogOut ).然后(()={

  Message.error(err 验证失败,请重新登录)

  下一步({路径:/ })

  })

  })

  }否则{

  //没有动态改变权限的需求可直接下一个()删除下方权限判断

  如果(有权限(存储。吸气剂。roles,to.meta.roles)) {

  next()//

  }否则{

  下一步({ path:“/401”,replace: true,query: { noGoBack: true }})

  }

  //可删

  }

  }

  }否则{

  /*没有标记*/

  if (whiteList.indexOf(to.path)!==-1) { //在免登录白名单,直接进入

  下一个()

  }否则{

  下一步(/login) //否则全部重定向到登录页

  NProgress.done() //如果当前页面是注册每次挂接后都不会触发,所以手动处理

  }

  }

  })

  router.afterEach(()={

  NProgress.done() //完成进度条

  })

  按需挂载,路由就需要知道用户的路由权限,也就是在用户登录进来的时候就要知道当前用户拥有哪些路由权限

  这种方式也存在了以下的缺点:

  全局路由守卫里,每次路由跳转都要做判断菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,而且路由不一定作为菜单显示,还要多加字段进行标识

  

菜单权限

  菜单权限可以理解成将页面与理由进行解耦

  

方案一

  菜单与路由分离,菜单由后端返回

  前端定义路由信息

  {

  名称:登录,

  路径:"/登录",

  组件:()=导入( @/pages/log in)。vue’)

  }

  名字字段都不为空,需要根据此字段与后端返回菜单做关联,后端返回的菜单信息中必须要有名字对应的字段,并且做唯一性校验

  全局路由守卫里做判断

  函数有权限(路由器,访问菜单){

  如果(白名单。(路由器的索引。路径)!==-1) {

  返回真实的

  }

  让menu=util。getmenubyname(路由器。名称、访问菜单);

  if (menu.name) {

  返回真实的

  }

  返回错误的

  }

  Router.beforeEach(async (to,from,next)={

  if (getToken()) {

  设userInfo=store。状态。用户。userInfo

  如果(!userInfo.name) {

  尝试{

  等待商店。派遣(获取用户信息)

  等待商店。分派( updateAccessMenu )

  if (to.path===/login) {

  下一个({ name: home_index })

  }否则{

  //Util.toDefaultPage([.路由器],收件人名称,路由器,下一个);

  下一个({.to,replace: true })//菜单权限更新完成,重新进入当前路线。

  }

  }

  捕捉(e) {

  if (whiteList.indexOf(to.path)!==-1) {//在免登录白名单中,直接输入。

  下一个()

  }否则{

  下一步(/login )

  }

  }

  }否则{

  if (to.path===/login) {

  下一个({ name: home_index })

  }否则{

  if (hasPermission(to,store.getters.accessMenu)) {

  util . todefaultpage(store . getters . access menu,to,routes,next);

  }否则{

  下一步({ path:“/403”,replace:true })

  }

  }

  }

  }否则{

  if (whiteList.indexOf(to.path)!==-1) {//在免登录白名单中,直接输入。

  下一个()

  }否则{

  下一步(/login )

  }

  }

  let menu=util . getmenubyname(to . name,store . getters . access menu);

  Util.title(菜单.标题);

  });

  Router.afterEach((to)={

  window.scrollTo(0,0);

  });

  每次路由跳转,都需要判断权限。这里的判断也很简单,因为菜单的名字和路由的名字是一一对应的,后端返回的菜单已经被权限过滤了。

  如果根据路由名称找不到对应的菜单,说明用户有访问权限。

  如果有许多路由,则在应用程序初始化时,可以只挂载不需要权限控制的路由。获取后端返回的菜单后,根据菜单与路由的对应关系,筛选出可访问的路由,并通过addRoutes动态挂载。

  这种方法的缺点:

  菜单需要与路线一一对应。前端增加新功能,需要通过菜单管理功能增加新菜单。如果菜单配置不正确,应用程序将无法正常使用全局路由保护。每一次路由跳转都必须进行判断。

  

方案二

  菜单和路由由后端返回。

  前端统一定义路由组件

  const Home=()=import(./pages/home . vue’);

  const UserInfo=()=import(./pages/userinfo . vue );

  导出默认值{

  家:家,

  用户信息:用户信息

  };

  后端组件返回以下格式

  [

  {

  姓名:家,

  路径:“/”,

  组件:“主页”

  },

  {

  姓名:家,

  路径:“/userinfo”,

  组件:“userInfo”

  }

  ]

  在通过addRoutes动态挂载后端返回路由之前,需要处理数据并用一个真实的组件替换component字段。

  如果存在嵌套路由,在设计后端功能时,要注意添加相应的字段,并对前端数据进行相应的处理。

  这种方法也有缺点:

  在全局路由守卫中,每一次路由跳转都要进行判断,前端和后端的配合度更高。

  

按钮权限

  

方案一

  按钮权限也可以用v-if来判断。

  但是如果页面太多,每个页面必须获取路由表中的用户权限角色和meta.btnPermissions,然后做出判断。

  这样,我就不举例了。

  

方案二

  通过用户自定义指令判断按钮权限。

  首先配置路由。

  {

  路径:“/权限”,

  组件:布局,

  名称:“权限测试”,

  元:{

  BTN权限:[admin , supper , normal]

  },

  //页面所需的权限

  孩子:[{

  路径:“晚餐”,

  组件:_ import( system/super ),

  名称:“权限测试页面”,

  元:{

  BTN权限:[admin , super ]

  }//页面所需的权限

  },

  {

  路径:“正常”,

  组件:_import(系统/正常),

  名称:“权限测试页面”,

  元:{

  BTN权限:[admin]

  }//页面所需的权限

  }]

  }

  用户定义的权限认证指令

  从“vue”导入Vue

  /* *权限说明* */

  const has=Vue.directive(has ,{

  bind: function (el,binding,vnode) {

  //获取页面按钮权限

  设btnPermissionsArr=[];

  if(binding.value){

  //如果命令传递一个值,则获取命令参数,并与当前登录的按钮权限进行比较。

  btnPermissionsArr=array . of(binding . value);

  }否则{

  //否则,获取路由中的参数,根据路由的btnPermissionsArr和当前登录的按钮权限进行比较。

  btnPermissionsArr=vnode . context . $ route . meta . BTN permissions;

  }

  如果(!vue . prototype . $ _ has(btnPermissionsArr)){

  El . parent node . remove child(El);

  }

  }

  });

  //权限检查方法

  vue . prototype . $ _ has=function(value){

  设isExist=false

  //获取用户按钮权限

  let btnPermissionsStr=session storage . getitem( BTN permissions );

  if(btnPermissionsStr==undefined btnPermissionsStr==null){

  返回false

  }

  if(value . index of(btnPermissionsStr)-1){

  isExist=true

  }

  返回isExist

  };

  导出{has}

  在所使用的按钮中,只需要引用v-has指令。

  El-button @ click= edit click type= primary v-has编辑/el-button

  

小结

  权限如何选择合适的方案,可以根据自己项目的方案,比如路线是否脱离菜单。

  权限需要前端和后端结合,前端尽量控制,更多的需要后台判断。

  这就是这篇关于vue权限管理的文章。有关vue权限管理的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: