RBAC角色权限
RBAC(基于角色的访问控制)后台管理系统的权限模型通过角色作为用户与权限之间的桥梁,实现灵活且安全的访问控制。以下是对该模型的详细解释:
系统默认内置一个超级管理账号,超级管理员拥有最高权限
账号与角色绑定 -> 角色与权限绑定 -> 权限与路由绑定
用户登录 -> token认证 -> 用户信息 -> 角色跟权限 -> 过滤路由和权限 -> 用户操作
1、账号管理
账号管理可新建账号,账号需要与部门、角色绑定,一个账号可绑定多个角色
{
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、角色管理
角色管理可给角色分配权限,权限包括页面权限、按钮权限、接口权限等,权限树的节点互相独立,勾上哪个节点就单独分配哪个节点权限
{
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、菜单管理
后端处理
- 路由树
路由这里为一维扁平路由,并且只有type: 1/2
两种类型
{
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
}
- 权限树
权限的数据结构跟路由的数据结构大致一样,只不过没有外链、内嵌、icon等路由专属字段,因为这是权限数据,所以只需要启用禁用、权限字符等关键信息即可。
[
{
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
}
}
]
菜单管理后端需要返回树形结构,根据 id
和 parentId
组装数据,在这里菜单树由前端mock
模拟后端操作,大概分为以下几步:
1、查询一维扁平路由、查询一维扁平权限列表,将路由和权限合并成一维数组
2、菜单管理这里需要查看到所有路由,无需判断角色权限、禁用路由
3、将扁平路由转换为树结构,转换规则 parentId === id
说明是其子节点,存储在children
字段内,若无子节点,children
为null
。
4、根据sort
字段给路由树排序
5、返回路由树
新增修改
- 渲染页面
前端调接口拿到路由树后渲染菜单树,在新增修改的时候需要注意,目录下可以添加目录和菜单,菜单下只能添加按钮,按钮无新增功能。
- 后端校验
后端接到前端调用新增修改接口数据时需要做过过滤和校验处理
校验规则:目录下可以添加目录和菜单,菜单下只能添加按钮,按钮无新增功能
根据type判断目录/菜单/按钮
数据结构:目录跟菜单类型接路由数据,按钮类型接权限数据
根据type判断目录/菜单/按钮
4、部门机构
[{
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
结构按照层级编码设计模式进行
层级关系 ID 结构
父节点 '01'
└─ 子节点1 '0101'
├─ 子节点1-1 '010101'
└─ 子节点1-2 '010102'
子节点2 '0102'
├─ 子节点1-1 '010201'
└─ 子节点1-2 '010202'
如果是扁平一维数据结构,需要根据 id
和 parentId
转换为树结构返回给前端,无子节点children: null