资讯专栏INFORMATION COLUMN

管理系统之权限的设计和实现

googollee / 1919人阅读

摘要:基本设计和分析前端服务端主要功能打开思否页面,根据页面的功能点,设计出相关的数据表,和管理系统需要的相关页面。

本文主要想对前端权限管理功能实现做一个分享,所以并不会对后台管理的框架结构做太详细介绍,如果有朋友对其他有兴趣可以留言。

基本设计和分析

前端 vue + elementui

服务端: node + mysql + nginx

主要功能

打开思否页面,根据页面的功能点,设计出相关的数据表,和管理系统需要的相关页面。
计划后台管理需要完成的功能:

权限管理(菜单权限到数据权限) -- 已完成

工作流 (问答和文章在某个条件内,提交需要走流程)-- 未完成

socket (对用户点赞,评论,系统通知等消息进行实时推送)-- 未完成

文件管理(将页面需要用到的文件上传管理,其他页面都统一访问文件库资源)-- 已完成

基本业务 (业务页面)-- 部分完成

模块相关介绍
模块 功能 页面编码 描述
登录 登录 login 菜单中不显示
401 401 401 角色无访问权限时进入这个页面
404 404 404 访问菜单不存在时进入这个页面
首页 首页 home
运维中心 opsCenter
- 问答管理 questionMan
- 专栏管理 blogMan
- 文章管理 articleMan
- 讲堂管理 liveMan
- 活动管理 activityMan
- 广告位 advertising
工作流 workflow
- 流程设计 processDesign
- 业务管理 businessMan
- 已办事项 finishedItems
- 未办事项 unfinishedItems
文件库 library
- 图片管理 imgMan
- 文件管理 fileMan
论坛配置 bbsConfig
- 轮播 carousel
- 技术频道 techSquare
- 通知 notices
- 标签类型管理 tagTypeMan
- 标签管理 tagMan
系统管理 sysMan
- 用户管理 userMan
- 角色管理 roleMan
- 菜单管理 menuMan
- 区域管理 areaMan
- 图表配置 chartConfig
- 系统日志 log
代码结构
├── admin                      // 打包产出文件
├── node_module                // npm加载所需的项目依赖模块
├── public                     // 静态入口
├── src                        // 源代码
│   ├── api                    // 所有请求
│   ├── assets                 // 主题 字体 图片等静态资源
│   ├── common                 // 全局公用配置
│   │   ├── config             // 配置全局路由权限和错误捕获
│   │   ├── mixin              // 一些vue公用的mixin
│   │   ├── js                 // 编写公有的方法
│   │   └── style              // 编写公有的样式
│   ├── components             // 全局公用组件
│   ├── directive              // 自定义指令
│   ├── router                 // 路由
│   ├── store                  // 全局 store管理
│   ├── views                  // view
│   ├── App.vue                // 入口页面
│   └── main.js                // 入口 加载组件 初始化等
├── static                     // 第三方不打包资源
├── .babelrc                   // babel-loader 配置
├── eslintrc.js                // eslint 配置项
├── .gitignore                 // git 忽略项
├── vue.config.js              // vue-cli@3.0+ 配置文件
└── package.json               // package.json
权限设计

进入正文,关于权限设计,围绕的是前端页面,但是会将前端和后端的逻辑都讲出来。

用户管理 创建

前端页面

看图中圈起来的地方,前端看到的逻辑是这样的:

当前用户为admin

树用右键操作admin创建的用户

树用右键操作创建的用户admin可以管理

就是创建了一个用户,这个用户创建的用户以及创建用户创建的用户,都可以被当前创建者管理。

接口逻辑

查询到数据库中所有的用户ID

通过用户ID和创建人ID的关系,通过建立树状数据,得到当前用户创建的用户树

递归从用户树中得到所有属于当前用户子集的用户ID

select * from table where id in (子集用户id)

通过这个逻辑,可以得到所有当前用户创建的子集,但是第一步有很大的问题,一旦用户数量巨大,这样查询会很慢。母目前只是为了功能实现,暂未考虑到性能方面,如果有好的方法,希望指点。

删除

前端页面

删除用户,调用接口判断用户是否有子集,存在->3,不存在->2

不存在直接删除

存在需要先将当前创建的用户转移给其他用户(其他用户不可为他的子集)

将用户转移成功,则此时子集为空 ->2

接口逻辑

查询到数据库中是否存在创建人ID为当前要删除的用户ID

存在则无法删除当前用户

前端调用户转移接口,将当前用户创建的用户转移给其他人后,此时可删除该用户

菜单管理

菜单设计的时候分为三个类型,管理平台,论坛,移动端,但是不一定会写完,感觉一个人写好累呀~~~~
通过菜单又分还有默认布局组件和页面组件的区分,布局组件为layout,页面组件则为他的子路由,通过嵌套的形式,组成一个完整的页面。

页面


目前页面上都是通过右键点击树组件,进入操作,如图所示,可以对菜单进行增删改查操作。

菜单字段的定义和相关用处
字段定义是这样的:
看到图中有这些字段,对主要字段说明:

菜单编码(对应前端页面的文件名,比如userMan, 渲染时就会找到 */userMan/index去resolve)

菜单组件 (指的是layout等,后面如果需要做多布局,通过这个设置页面即可有不同布局)

-- ----------------------------
-- bbs_menu
-- ----------------------------
DROP TABLE IF EXISTS `bbs_menu`;
CREATE TABLE `bbs_menu` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `pid` INT(11) DEFAULT "0",
  `type` tinyint(4) NOT NULL DEFAULT "1" COMMENT "菜单类型: 1. 管理平台菜单 2. BBS菜单 3. 移动端菜单",
  `code` VARCHAR(48) NOT NULL COMMENT "菜单编码",
  `name` VARCHAR(48) NOT NULL COMMENT "菜单名称",
  `component` tinyint(4) NOT NULL COMMENT "对应组件: -1. 根节点 1. 页面组件 2.默认布局 3456...扩展布局",
  `icon` VARCHAR(128) DEFAULT NULL COMMENT "菜单图标",
  `alias` VARCHAR(128) DEFAULT NULL COMMENT "别名",
  `redirect` VARCHAR(128) DEFAULT NULL COMMENT "重定向路径: 配置菜单编码或URL",
  `sort` INT(11) NOT NULL,
  `desc` VARCHAR(128) DEFAULT NULL,
  `status` tinyint(4) NOT NULL DEFAULT "1" COMMENT "状态: 0:停用,1:启用(默认为1)",
  `create_user` INT(11) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_user` INT(11) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `delete_user` INT(11) DEFAULT NULL,
  `delete_time` datetime DEFAULT NULL,
  `flag` tinyint(4) NOT NULL DEFAULT "1" COMMENT "状态: 0:删除,1:可用(默认为1)",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT="菜单表";
    id: "", // *唯一ID
    pid: "", // *父ID
    type: "", // *菜单类型
    code: "", // *菜单编码
    name: "", // *菜单名称
    component: "", // *菜单组件
    icon: "", // 菜单图标
    redirect: "", // 重定向路径
    sort: "", // *排序
    desc: "", // 描述
    status: 1 // *状态: 0:停用,1:启用(默认为1)"

有什么用处呢和好处呢,就个人而言,就是觉得把路由表放在数据库,让项目更易于维护,在页面中通过一个匹配逻辑,可以将所有字段组装成为可以使用的路由表:

// 得到页面路径
function getPath (arr, child, code) {
  const pItem = arr.find(item => child.pid === item.id)
  // 当前元素还存在父节点, 且父节点不为根节点
  if (arr.find(item => pItem.pid === item.id && item.pid > -1)) {
    getPath(arr, pItem, `${pItem.code}/${code}`)
  } else {
    return `${pItem.code}/${code}`
  }
}
// 对基础数据的处理
              item.meta = {}
              item.meta.title = item.name
              item.meta.icon = item.icon
              item.meta.id = item.id
              // 使路由名字具有唯一性
              item.name = item.name + index
              // 设置对应的页面路径
              item.path = "/" + item.code
// 设置页面对应的组件 对应组件: -1. 根节点 1. 页面组件 2.默认布局 3456...扩展布局
              switch (item.component) {
                case -1:
                  console.log("根节点,已经过滤掉了")
                  break
                case 1:
                  item.component = resolve => require([`@/views/${getPath(menu, item, item.code)}/index`], resolve)
                  break
                case 2:
                  item.component = Layout
                  break
                default:
                  item.component = resolve => require(["@/views/errorPage/401"], resolve)
                  break
              }

通过这种方式,在设置页面权限的时候,只需要接口设置当前角色对应的菜单,用户查询的时候能获取到的就是当前分配给他的权限,将这个权限组装成路由表,即可。

数据权限

上面说的是菜单的配置,以及生成。然后和每个页面相关的数据权限,需要点击到页面级别的菜单才可以访问到,如图:

选中一个菜单之后,可以对这个菜单添加数据权限的控制,比如添加,编辑,删除等操作。

数据权限的实现

主要是字段设计,所以对图中字段(开发人员录入)详细说明:

功能编码 (页面编码:功能编码,主要用于前端控制显隐)

功能api (接口编码,后端通过判断用户是否存在这个编码,来判断是否存在操作权限)

请求方式 (restfulApi情况下,因为api编码相同,需要根据请求方式来判断用户的操作权限)

前端实现

分配完权限之后,前端页面在对应的按钮或要操作的dom上,通过v-if 功能编码是否存在来设置操作权限的显示隐藏。
但是前端的显隐一旦用户绕过页面去访问接口即可,所以数据权限前端只是操作显隐,具体实现还在后端。

后端实现

做一个数据权限中间层,用户访问时中间层判断当前访问的接口用户是否拥有权限

怎么判断,通过前端设置的功能api和请求方式,去表中查询当前用户角色是否可访问

可访问继续往下走,不能访问就拒绝了

角色管理

用户存在了,菜单和数据权限也配置好了,但是需要角色去将他们关联到一起。

绑定用户

这里设置的逻辑是一个用户只能绑定一个角色。
角色管理页面,还是右键树组件,可以看到绑定用户的选项

分配权限

同样是右键,可以开始对角色进行分配权限的操作

左边是页面的权限分配,选中页面之后,右边会出现数据权限的分配:

继承式的分配权限

总共有100个权限

a有50个,a给b分配时,只能分配50个

假设a给b分配了30个,c为b的下级,d为c的下级

c此时无权限,a或b能分配30个给c,但由于c无权限,a或b分配给d时,分配的列表为空

总结

创建用户
创建菜单
创建角色
用户绑定角色,角色分配权限
完成

最后

案例地址

node服务

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105079.html

相关文章

  • 途牛原创|途牛无线权限系统架构设计与实践

    摘要:认为权限授权实际上是的问题。具体的权限,正向授权与负向授权。应用建模业务场景权限管理鉴权设计应用建模系统架构上支撑权限系统灵活配置,不僵硬字段,不僵硬行为,基于各种业务权限管控的特征灵活设计。表示许可权与角色之间多对多的指派关系。 序 之前写过一篇大话权限中心的PHP架构之道,主要是从软件工程角度介绍,如何通过编码规范、依赖管理、数据源架构、事务处理、单元测试等技术,来保障权限系统的高...

    TwIStOy 评论0 收藏0
  • 途牛原创|途牛无线权限系统架构设计与实践

    摘要:认为权限授权实际上是的问题。具体的权限,正向授权与负向授权。应用建模业务场景权限管理鉴权设计应用建模系统架构上支撑权限系统灵活配置,不僵硬字段,不僵硬行为,基于各种业务权限管控的特征灵活设计。表示许可权与角色之间多对多的指派关系。 序 之前写过一篇大话权限中心的PHP架构之道,主要是从软件工程角度介绍,如何通过编码规范、依赖管理、数据源架构、事务处理、单元测试等技术,来保障权限系统的高...

    姘搁『 评论0 收藏0
  • 途牛原创|大话权限中心PHP架构

    摘要:权限中心的依赖声明声明依赖关系检查代码规范声明开发依赖命名空间检查代码规范,执行单元测试。单元测试持续交付一切都如此的完美,没有测试,又如何可以证明这件事情的完美,又如何可以保障交付的质量。 序 权限管理是无线运营系统中的核心模块,通过访问控制策略的配置,来约定人与资源的访问关系。 本文着重讲解如何通过PHP来构建一个灵活、通用、安全的权限管理系统。 关于权限 首先我们来聊聊权限。 权...

    miracledan 评论0 收藏0
  • Spring Security

    摘要:框架具有轻便,开源的优点,所以本译见构建用户管理微服务五使用令牌和来实现身份验证往期译见系列文章在账号分享中持续连载,敬请查看在往期译见系列的文章中,我们已经建立了业务逻辑数据访问层和前端控制器但是忽略了对身份进行验证。 重拾后端之Spring Boot(四):使用JWT和Spring Security保护REST API 重拾后端之Spring Boot(一):REST API的搭建...

    keelii 评论0 收藏0
  • API网关设计(一)Token多平台身份认证方案

    摘要:网关设计一之多平台身份认证方案随着的发展现如今早已不是当年的登陆单一模式,而不久的到来又会带来无人车等其他设备的接入。所以为了应对将来的时代的变化,一个好的多平台认证登陆方案是切实所需。 API网关设计(一)之Token多平台身份认证方案 随着4g的发展现如今早已不是当年的web登陆单一模式,而不久5g的到来又会带来无人车等其他设备的接入。所以为了应对将来的时代的变化,一个好的多平台认...

    leon 评论0 收藏0

发表评论

0条评论

googollee

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<