前端权限控制系统的实现思路

一、项目主体

  • 管理平台(代称为ManagePlatform、MP)
  • 一级菜单(代称M)
  • 二级菜单(代称m)
结构图:

二、应用场景

不同用户拥有不同的菜单权限:
  • 管理员(manageUser)拥有可见全部菜单的权限

  • 用户1(user1)拥有可见M1下的全部菜单的权限

  • 用户2(user2)拥有可见M1和M2下的全部菜单的权限

  • 用户3(user3)拥有可见M1、M2下全部及M3的m31菜单权限

三、实现思路

权限控制:
  1. 导航栏菜单是否可见
  2. 校验url能否跳转
服务端:
  1. 接口返回当前用户的权限数据,并实际菜单结构保持一致(MP中包含M1、M2、M3,M1中包含m11、m12,...)
  2. 其中每个菜单包含id(菜单id)、name(菜单名称)、children(子集菜单)等必要属性
前端:
  1. 路由默认配置全部的菜单,但均为隐藏状态(登录和首页无权限,无需限制)
  2. 通过接口获取到该用户的权限数据,并与默认路由进行比对,将对应菜单部分设置为可显示(有权限)
  3. 将菜单所有id存储到本地list,在路由跳转之前校验此路由的id是否包含在list中,如果有,则执行跳转,否则进入到首页(表示没有权限)

四、代码模拟

默认路由routes:
export default [
  {
    path: '/M1',
    redirect: '/M1/m11',
    component: Layout,
    name: 'M1菜单',
    meta: {
      extraMenuId: 1,
      hidden: true
    },
    children: [{
      path: '/M1/m11',
      name: 'm11菜单',
      component(resolve) {
        require(['@views/M1/m11'], resolve);
      },
      meta: {
        extraMenuId: 2,
        hidden: true,
      }
    }, {
      path: '/M1/m12',
      name: 'm12菜单',
      component(resolve) {
        require(['@views/M1/m12'], resolve);
      },
      meta: {
        extraMenuId: 3,
        hidden: true,
      }
    }]
  },
  {
    path: '/M2',
    redirect: '/M2/m21',
    component: Layout,
    name: 'M2菜单',
    meta: {
      extraMenuId: 4,
      hidden: true
    },
    children: [{
      path: '/M2/m11',
      name: 'm21菜单',
      component(resolve) {
        require(['@views/M2/m21'], resolve);
      },
      meta: {
        extraMenuId: 5,
        hidden: true,
      }
    }, {
      path: '/M2/m22',
      name: 'm22菜单',
      component(resolve) {
        require(['@views/M2/m22'], resolve);
      },
      meta: {
        extraMenuId: 6,
        hidden: true,
      }
    }]
  },
  {
    path: '/M3',
    redirect: '/M3/m31',
    component: Layout,
    name: 'M3菜单',
    meta: {
      extraMenuId: 7,
      hidden: true
    },
    children: [{
      path: '/M3/m31',
      name: 'm31菜单',
      component(resolve) {
        require(['@views/M3/m31'], resolve);
      },
      meta: {
        extraMenuId: 8,
        hidden: true,
      }
    }, {
      path: '/M3/m32',
      name: 'm32菜单',
      component(resolve) {
        require(['@views/M3/m32'], resolve);
      },
      meta: {
        extraMenuId: 9,
        hidden: true,
      }
    }, {
      path: '/M3/m33',
      name: 'm33菜单',
      component(resolve) {
        require(['@views/M3/m33'], resolve);
      },
      meta: {
        extraMenuId: 9,
        hidden: true,
      }
    }]
  },
  {
    path: '/login',
    name: '登录',
    component(resolve) {
      require(['@views/login'], resolve);
    },
    meta: {
      hidden: true
    }
  },
  {
    path: '/home',
    name: '首页',
    component(resolve) {
      require(['@views/home'], resolve);
    },
    meta: {
      hidden: true
    }
  },
  {
    path: '*',
    redirect: '/home',
    meta: {
      hidden: true
    }
  }
]
复制代码
菜单id数据menuIdList与路由routes匹配:
// 因管理端菜单展示只展示两层,故只需遍历前两层路由
routes.forEach((item) => {
  if (menuIdList.indexOf(item.meta.extraMenuId) >= 0) {
    item.meta.hidden = false;
    if (item.children && item.children.length) {
      item.children.forEach((child) => {
        if (menuIdList.indexOf(child.meta.extraMenuId) >= 0) {
          child.meta.hidden = false;
        }
      })
    }
  }
});
复制代码
公共方法判断id是否存在:
/**
 * 判断menuId是否存在与Localtorage中
 * @param menuId
 */
export function getMenuAuth(menuId) {
  const menuIdList = JSON.parse(getMenuIdList());
  return menuIdList.indexOf(menuId) >= 0;
}
复制代码
路由守卫校验:
router.beforeEach((to, from, next) => {
  // 判断是否已登录,未登录则进入登录页面
  if (getToken()) {
    if (to.path === '/login') {
      next();
    } else {
      if (to.path === '/' || to.path === '/home') {
        next();
        return;
      }
      // url路由权限校验,没有权限则进入home页面
      if (getMenuAuth(to.meta.extraMenuId)) {
        next();
      } else {
        next('/home');
      }
    }
  } else {
    next('/login');
  }
})
复制代码

以上仅为项目开发过程中的个人思路,如有更好的想法思路请在评论区留言,谢谢!

转载于:https://juejin.im/post/5b0cf2d4f265da08e12f0e3b

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值