Vue3 实现 RBAC 权限管理
RBAC的基本概念
- RBAC本质上就是一个授权的过程通过 用户 —> 角色---->资源
为啥要用RBAC
- 一个系统中用户是非常多的,对于不同的用户,展示的内容也是不同的,如果为每一个用户都单独的设置权限那需要创造出多少提条数据,例如:一个系统有30个菜单,100个用户,一对一授权就是30 * 100 ,每一个菜单项基本有增删改查,那就是30 * 100 * 4用户越多产生的数据越多,后期增删改查统统要遍历所有的数据,设计是非常糟糕的,效率极低。
- 若果采用RBAC 设计模式,引入了角色就会简单很多,10个用户先分为管理员和普通用户,通过角色去查对应的资源 ,那就是 30 * 4 *2,后期无论增加多少用户,只要不是增加角色种类数据就不会变。
RBAC的概述
- 总的来说就是围绕着一句话
通过用户的id查询对应的角色再查询对应的资源,从而绑定用户与资源之间的关系
RBAC数据库的设计
-
id 、crated_At、updated_at、deleted_at(逻辑删除用的) ,这些是非关联表的必备字段
-
用户表 (储存用户信息的字段)
- username
- password
- avatar
- status(用户的状态)
- phone
-
角色表 (系统角色的信息)
- name
- status(角色状态)
- remark(角色标识)
- description(角色描述)
-
资源表 (菜单表或者其他的一些系统资源,这里采用菜单作为资源)
- name(菜单名称)
- pid(资源关联成树形结构(目录为0,菜单为id、按钮为NULL))
- enabled(是否启用)
- grade(分组:0目录,1菜单,2按钮)
- path(前端路由跳转的路径,路径要全)
- component(前度端组件的名称(一般大写))
- icon_cls(菜单的图标)、keep_alive(组件是否缓存)
- require_auth(是否需要权限认证)
- remark(菜单的唯一标识、用于后期的权限认证处理和动态路由以及动态菜单的关键字)
- description(菜单的描述)
- level (菜单的等级、菜单的排序(同一组菜单下的显示顺序))
-
用户角色表(用户与角色多对多产生的关联表)
- role_id (角色的id)
- user_id (用户的id)
-
角色资源表(角色与资源多对多产生的关联表)
- rid (角色的id)
- mid (菜单的id)
- prim (权限码 对应的是菜单的remark字段) 这个字段的设计是方便我们获取权限码
- 若不设置也可以通过关联菜单查到,但每次都要关联后端写起来太麻烦了,直接就设计下这里了
表的设计
用户表实例
角色表实例
菜单(资源)表
角色用户表实例
角色资源表实例
后端设计 egg.js
技术概要
- egg.js 简单快速
- sequelize Sequelize 是一个基于 promise 的 Node.js ORM
- mysq 数据存储
- jwt 生成token
- svg-captcha 生成验证码
后端系统主要的架构
- controller (用于数据的检验和放回结果)
- service (结合sequelize 对数据的操作)
- model (定义数据模型、完成表的映射关系)
- router (定义路由)
- middleware (中间件 权限的设置)
- heeper (返回结果的统一处理)
sequelize 模型展示
- 用户表
'use strict'
module.exports = (app) => {
const {
STRING, INTEGER, DATE, BOOLEAN } = app.Sequelize
const User = app.model.define(
'users', //数据库里的对应表名
{
id: {
type: INTEGER, // 类型
primaryKey: true,
autoIncrement: true, // 自增
allowNull: true, // 允许为null 在插入数据的时候不用填id
},
username: STRING(30),
password: INTEGER,
avatar: STRING,
phone: INTEGER,
status: {
type: BOOLEAN,
defaultValue: true,
},
createdAt: DATE,
updatedAt: DATE,
deletedAt: DATE,
},
{
tableName: 'users', //指定与数据库对应的表名称
timestamps: true, // 启用自动更新时间
}
)
// associate 函数 设置模型之间的关联
User.associate = function () {
// 多对多关联 关联的模型是Role
User.belongsToMany(app.model.Role, {
// through 通过中间表RoleUser模型进行关联
through: app.model.RoleUser,
// 外键即 中间表RoleUser中与当前模型的关联字段userId
foreignKey: 'userId',
// 外键 中间表RoleUser中与当Role模型的关联字段roleId
otherKey: 'roleId',
})
}
return User
}
- 角色表
'use strict'
module.exports = (app) => {
const {
STRING, INTEGER, DATE, BOOLEAN } = app.Sequelize
const Role = app.model.define(
'roles',
{
id: {
type: INTEGER,
autoIncrement: true,
allowNull: true,
primaryKey: true,
},
name: {
type: STRING(30),
primaryKey: true,
},
remark: STRING,
description: INTEGER,
status: {
type: BOOLEAN,
defaultValue: true,
},
createdAt: DATE,
updatedAt: DATE,
deletedAt: DATE,
},
{
tableName: 'roles', //指定表名称
timestamps: true,
}
)
Role.associate = function () {
// 角色和用户是多对多
Role.belongsToMany(app.model.User, {