Skip to content

RBAC角色权限

RBAC(基于角色的访问控制)后台管理系统的权限模型通过角色作为用户与权限之间的桥梁,实现灵活且安全的访问控制。以下是对该模型的详细解释:

系统默认内置一个超级管理账号,超级管理员拥有最高权限

账号与角色绑定 -> 角色与权限绑定 -> 权限与路由绑定

用户登录 -> token认证 -> 用户信息 -> 角色跟权限 -> 过滤路由和权限 -> 用户操作

1、账号管理

账号管理可新建账号,账号需要与部门、角色绑定,一个账号可绑定多个角色

tsx
{
    id: 1, // 账号id
    deptId: "100", // 部门id
    deptName: "研发部门", // 部门名称
    userName: "admin", // 用户名-用于登录
    nickName: "超级管理员", // 用户昵称-用于显示
    email: "2547096351@qq.com", // 邮箱
    phone: "15888888888", // 电话
    sex: 1, // 性别 0女 1男 2未知
    avatar: "https://ooo.0x0.ooo/2025/04/10/O0dG7r.jpg", // 用户头像
    status: 1, // 是否启用 0停用 1启用
    description: "系统初始用户", // 描述
    roles: ["admin"], // 角色权限 Array[string]
    loginIp: "0:0:0:0:0:0:0:1", // 登录ip
    loginDate: "2025-03-31 10:30:59", // 登录时间
    createBy: "admin", // 创建人
    createTime: "2024-03-19 11:21:01", // 创建时间
    updateBy: null, // 修改人
    updateTime: null, // 修改时间
    admin: true // 是否为超级管理员 true是 false否
}

2、角色管理

角色管理可给角色分配权限,权限包括页面权限、按钮权限、接口权限等,权限树的节点互相独立,勾上哪个节点就单独分配哪个节点权限

typescript
{
    id: 1, // 角色id
    name: "超级管理员", // 角色名称
    code: "admin", // 角色权限标识
    sort: 1, // 排序
    status: 1, // 是否启用 0停用 1启用
    admin: true, // 是否为超级管理员 true是 false否
    description: "默认角色,超级管理员,上帝角色", // 描述
    createBy: null, // 创建人
    createTime: "2024-03-27 11:21:01", // 创建时间
    updateBy: null, // 修改人
    updateTime: null // 修改时间
}

3、菜单管理

后端处理

  1. 路由树

路由这里为一维扁平路由,并且只有type: 1/2两种类型

typescript
{
    id: "01", // 路由id
    parentId: "0", // 顶层路由 parentId: 0
    path: "/home", // 路由path
    name: "home", // 路由name
    component: "home/home", // 路由跳转的文件路径,默认在src/views内,这里就是src/views/home/home.vue
    meta: {
    title: "home", // 国际化key,无对应Key则直接展示
      hide: false, // 是否隐藏此路由-不显示但可访问
      disable: false, // 是否停用此路由-不显示且不可访问
      keepAlive: false, // 是否缓存组件
      affix: true, // 固定在Tabs栏上-开启后Tabs栏无关闭按钮
      link: "", // 是否外链
      iframe: false, // 是否内嵌外链窗口
      roles: ["admin", "common"], // 路由角色权限
      svgIcon: "home", // svg菜单图标,优先级高于icon,取src/assets/svgs内的svg文件
      icon: "", // 普通icon菜单图标,默认取arco.design图标
      sort: 1, // 排序字段
      type: 2 // type 1目录 2菜单 3按钮
   },
   children: null // 存储子节点字段,默认为null
}
  1. 权限树

权限的数据结构跟路由的数据结构大致一样,只不过没有外链、内嵌、icon等路由专属字段,因为这是权限数据,所以只需要启用禁用、权限字符等关键信息即可。

typescript
[
  {
    id: "130101", // 权限id-权限是在对应路由下添加的,所以id取层级编码设计模式,路由id:1301,权限id:130101
    parentId: "1301", // 父级路由id:1301
    meta: {
      title: "新增按钮", // 国际化key,无对应Key则直接展示
      hide: false, // 是否隐藏此路由-不显示但可访问
      disable: false, // 是否停用此路由-不显示且不可访问
      roles: ["admin"], // 角色权限
      permission: "sys:btn:add", // 权限标识符
      sort: 1, // 排序字段
      type: 3 // type 1目录 2菜单 3按钮
    }
  },
  {
    id: "130102",
    parentId: "1301",
    meta: {
      title: "编辑按钮",
      hide: false,
      disable: false,
      roles: ["admin"],
      permission: "sys:btn:edit",
      sort: 2,
      type: 3
    }
  }
]

菜单管理后端需要返回树形结构,根据 idparentId 组装数据,在这里菜单树由前端mock模拟后端操作,大概分为以下几步:

1、查询一维扁平路由、查询一维扁平权限列表,将路由和权限合并成一维数组

2、菜单管理这里需要查看到所有路由,无需判断角色权限、禁用路由

3、将扁平路由转换为树结构,转换规则 parentId === id 说明是其子节点,存储在children字段内,若无子节点,childrennull

4、根据sort字段给路由树排序

5、返回路由树

新增修改

  1. 渲染页面

前端调接口拿到路由树后渲染菜单树,在新增修改的时候需要注意,目录下可以添加目录和菜单,菜单下只能添加按钮,按钮无新增功能。

  1. 后端校验

后端接到前端调用新增修改接口数据时需要做过过滤和校验处理

校验规则:目录下可以添加目录和菜单,菜单下只能添加按钮,按钮无新增功能根据type判断目录/菜单/按钮

数据结构:目录跟菜单类型接路由数据,按钮类型接权限数据根据type判断目录/菜单/按钮

4、部门机构

typescript
[{
  id: "100", // 部门id
  parentId: "0", // 父级id,'0'为顶层节点
  name: "xxx机构有限公司", // 部门名称
  leader: "兔子先森", // 负责人名称
  phone: "15888888888", // 电话
  email: "2547096351@qq.com", // 邮箱
  sort: 1, // 排序
  status: 1, // 状态 0禁用 1启用
  description: "这是总部门", // 描述
  createBy: "admin", // 创建人
  createTime: "2024-03-19 11:21:01", // 创建时间
  updateBy: "admin", // 修改人
  updateTime: "2024-09-09 10:08:25", // 修改时间
  children: null // 存储下级部门字段,默认为null
},
 {
   id: "10001",
   parentId: "100",
   name: "华中总部",
   leader: "小唐",
   phone: "",
   email: "",
   sort: 1,
   status: 1,
   description: "这里是华中总部",
   createBy: "admin",
   createTime: "2024-03-19 11:21:01",
   updateBy: "admin",
   updateTime: "2024-09-09 17:30:40",
   children: null
 }
]

id结构按照层级编码设计模式进行

json
层级关系       ID 结构
父节点        '01'
└─ 子节点1    '0101'
   ├─ 子节点1-1 '010101'
   └─ 子节点1-2 '010102'
   子节点2    '0102'
   ├─ 子节点1-1 '010201'
   └─ 子节点1-2 '010202'

如果是扁平一维数据结构,需要根据 idparentId 转换为树结构返回给前端,无子节点children: null

基于 MIT 许可发布