前言

要弄清楚这个问题,我们先来看看什么是权限?个人认为,权限就是一系列用户可用的系统资源的整合,可以大致分为以下三类:

  • 菜单权限:用户使用的菜单、查看的页面等。
  • 操作权限:系统页面中的交互功能按钮,如编辑,删除,新增等。
  • 数据权限:用户在页面中查看的数据内容,业务系统数据一般存在机密性,不同身份的用户查看的数据范围也有所不同。

了解了权限,那么 权限管理 也就比较清晰了,其实就是对系统用户访问资源的管理。根据业务要求的不同,用户看到的菜单、使用的功能、查看的数据都有所不同。

那么为什么要控制访问权限呢?因为不同的用户所负责的业务范围是不同的,比如管理者可以看到所有下属的信息,但是普通只能看到自己的;比如行政可以看到所有人的打卡记录,而普通员工只能看自己的;比如财务可以看到所有人的工资,而普通员工只能看到自己的....等等等等,

这都离不开 权限管理,通过为系统用户分配不同的权限,以达到精准控制的目的。

权限关系

1.角色和人员: 一个角色可以包含但不限于一个成员,一个成员可以被分配至多个权限角色中(取和值,即取多个角色权限的和值)

2.角色和菜单: 多对多关系:一个角色有多个菜单,一个菜单可以分配给多个角色

3.角色和权限资源管理: 多对多关系:一个角色有多个权限资源,一个权限资源可以分配给多个角色

前端权限管理思路_序列化

思路跟方案

1.当用户开始访问

2.用户登录成功(并且拉取权限接口)

3.降权限数据保存到session中

4.根据获取的权限,对当前的路由进行序列化,不在该用户权限内的菜单排除序列化

5.文件目录和结构

├── src
	├──	api
		└── sys.rbac.service.js
	├──	directive
		├── directives.js
		└── index.js
	├── layout
		├── components/Sidebar
			└── index.js
	├── router
		└── index.js
	├── store
		├──	modules
			└── permission.js
		└──	getters.js
	├── main.js
	└── permission.js

前端权限管理思路_白名单_02

序列化代码如下

const component = modules[`你的组件路径`]?.default;
const route = {
  path: path,
  name: path + item.name,
  meta: {
    title: item.name,
    svgIcon: 'dashboard',
    affix: false,
  },
};

路由js(router.js),异步加入路由菜单信息

permissionStore.dynamicRoutes.forEach((route: any) => {
   router.addRoute(route);
});

permission指令注册

/** 权限指令,和权限判断函数 checkPermission 功能类似 */
export const permission: Directive = {
  mounted(el, binding) {
    const { value: permissionRoles } = binding;
    const { roles } = useUserStoreHook();
    if (Array.isArray(permissionRoles) && permissionRoles.length > 0) {
      const hasPermission = roles.some((role) => permissionRoles.includes(role));
      // hasPermission || (el.style.display = "none") // 隐藏
      hasPermission || el.parentNode?.removeChild(el); // 销毁
    } else {
      throw new Error(`need roles! Like v-permission="['admin','editor']"`);
    }
  },
};

使用办法

<el-button
  v-permission="['TRAINING:PLAN:UPDATE@PUT']"
  type="primary"
  >编辑</el-button
>

加入路由白名单

import { type RouteLocationNormalized } from 'vue-router';

/** 免登录白名单(匹配路由 path) */
const whiteListByPath: string[] = ['/login'];

/** 免登录白名单(匹配路由 name) */
const whiteListByName: string[] = [];

/** 判断是否在白名单 */
const isWhiteList = (to: RouteLocationNormalized) => {
  // path 和 name 任意一个匹配上即可
  return whiteListByPath.indexOf(to.path) !== -1 || whiteListByName.indexOf(to.name as any) !== -1;
};

export default isWhiteList;

转载来源:https://juejin.cn/post/7359475637205876770