权限系统设计-角色资源设计

前言

资源是一个抽象概念,包括系统所需要控制的所有对象,例如文件、菜单、按钮、任务等等,本章以最常用的菜单、按钮作为代表!

角色是权限设计的核心,用来控制资源的权限,角色也是数据权限的"阀门"。本章详细讨论角色的设计及资源设计。

角色设计

按照惯例,我们从属性、功能、关联关系三个维度考虑角色设计:

  • 属性 大概包括角色名称、备注信息、ID、状态等
  • 功能 设置用户、分配资源权限、刷新权限等
  • 关联关系 关联用户、关联资源等

经过思考梳理后,形成以下花型图:

通过花型图,总结如下:

  • 属性中 绿色 部分为角色对应的业务属性,蓝色部分为审计属性
  • 功能中 橙色 部分为管理功能,红色 部分为状态相关,蓝色部分为关联关系功能

为了权限设计的简洁,我们不考虑角色互斥条件。互斥功能,随着业务复杂性的提高,会导致权限管理的混乱!角色继承是默认的条件,比如用户只能分配拥有的资源权限,避免造成权限窃取泄露

角色属性

角色在设计上相对简单,主要包括以下属性:

  • ID 没有实际意义,用来适配框架(通用的增删改查操作)
  • 角色名称 一般用来标记业务相关的名称
  • 是否默认 用于处理人员直接分配资源权限(离散型权限)
  • 状态 角色的状态管理,生效、失效等功能
  • 备注 角色的备注说明信息
  • 审计属性前面章节已详细说明,此处不再赘述

某些业务场景下,资源权限比较分散,且互不重叠,即离散型权限:比如A用户需要X资源权限,B用户需要Y权限,此时建立角色反而冗余,可以直接对用户分配权限,为了权限的统一处理,此时我们针对每个用户创建一个默认角色进行处理

角色功能

角色主要包含以下功能:

  • 新增 新添加一个角色,必填字段角色名称
  • 修改 修改角色名称及备注信息
  • 删除 删除角色,该功能有一定的风险,删除后权限会失效
  • 查询 角色状态及名称查询
  • 明细 查看角色的详细信息
  • 刷新权限 分配资源权限后刷新缓存信息,使权限生效
  • 资源权限 分配菜单按钮资源权限
  • 添加用户 角色关联多个用户信息,从角色维度中进行用户关联
  • 停用 停用角色,使之数据权限失效
  • 启用 启用停用的角色

为提高效率在项目启动时会将资源及角色信息进行缓存(功能设计章节中描述过),分配完资源权限后需要刷新缓存使之生效(功能数量少时可将该功能集成到分配资源权限功能中)。

每一个功能都是由URL+Method进行唯一标识,角色分配资源后,用户访问该功能,通过URL+Method定位到按钮后到缓存查询对应的角色,从用户角色列表中查看是否包含该角色,从而完成鉴权,具体请查看前面的功能设计章节。

资源设计

资源包括菜单和按钮,都通过URL+Method进行访问。菜单中包含按钮,按钮又称为功能,每个功能可以定义数据权限,所以对于按钮而言即包括资源权限定义又包含数据权限关联。

同样通过功能、属性和关联关系维度来梳理下资源设计,经过整理具体如下:

从花型图上菜单和按钮拥有共同的资源属性,具体为:

  • ID 无实际意义,仅满足框架的通用操作
  • 资源ID 对应菜单或按钮的ID
  • 资源类型 菜单或按钮标识
  • 请求URL 请求该资源的URL 例如/api/user/search
  • 请求方法 请求该资源的请求方法 例如 POST

在资源设计中URL+Method为资源的唯一索引。通过资源的抽象,在系统中通过RequestContext(请求封装)获取请求的URL及方法就可以进行资源的查询定位,从而进行权限的相关操作。

菜单设计

菜单属性

在权限系统中,菜单是按钮的集合,菜单作为功能的"门户"也是资源权限的第一道"阀门",主要包含如下属性:

  • ID 菜单资源的ID,用来标识该资源
  • 菜单名称 菜单的名称,例如用户管理、角色管理等
  • 父菜单ID 菜单是一个树结构,有父菜单,如果是跟菜单则父菜单ID为空
  • 菜单类型 通过类型来区分不同类型的菜单,例如业务型、管理型等,权限系统只加载管理类型菜单
  • 图标 主要适配前端显示
  • 优先级 同级菜单优先级低的排列在前
  • 是否隐藏 隐藏后不显示
  • 是否忽略权限 设置后不再进行权限过滤
  • 审计属性不再赘述

菜单功能

菜单是一个属性结构,拥有子菜单及跟菜单的功能,具体如下:

  • 查询 根据菜单名称查询菜单
  • 明细 查看菜单的详细信息
  • 新增子菜单 菜单中添加子节点,建议最多三级菜单
  • 新增根菜单 作为单独的功能,方便根节点对应的父节点拥有特殊的定制值
  • 修改 通过修改属性中的忽略授权是否隐藏达到对应的功能

菜单在权限系统中根据用户角色进行资源验证并加载,设置忽略权限后,该菜单总是会加载。菜单是在用户登录后进行加载,明确用户是基础(需要明确用户的角色)。系统不对无登录菜单进行管理。

按钮设计

按钮也就是功能,是系统授权的核心,同时拥有资源权限和数据权限,资源权限用于表示能否操作,数据权限表示操作那些数据!

按钮属性

每个按钮都关联到菜单,我们设置权限时通过选择菜单展示对应的按钮,进行按钮的权限设置。隐藏的菜单不影响按钮权限的校验。按钮的具体属性如下:

  • ID 按钮资源的ID,全局唯一,格式为菜单ID:按钮功能,例如user:search 表示用户查询按钮
  • 按钮名称 用于表示功能的简要名称
  • 菜单ID 关联的菜单ID
  • 子标题 用于在资源权限设置中分组,例如 按照功能类型分组,在具体菜单下分为 读取相关 写入相关等
  • 是否忽略授权 忽略授权后,不对该按钮进行角色授权的验证,只要登录就能看到该按钮
  • 是否忽略鉴权 勾选忽略授权后才可以勾选该功能,设置后不需要登录即可看到该按钮
  • 备注 按钮的说明信息

鉴权和授权只是资源权限关联的功能,不影响数据权限的功能,例如用户查询功能,可以不登录就能看到,但能查询哪些数据是数据权限决定的。 子标题在自定义权限分组时尤其有用,面对复杂的业务系统,可以根据业务的需要来定义分组,更便于业务资源权限的管理。

按钮功能

按钮的功能除了自身的基础功能外还包含设置数据权限对应的功能,具体如下:

  • 新增 新增加一个按钮,必须关联菜单
  • 复制新增 复制一个已有的按钮修改对应的信息,创建新按钮
  • 删除 删除按钮,对应的资源权限和数据权限都将失效
  • 查询 按照名称查询按钮
  • 明细 查看按钮的明细信息
  • 修改 修改按钮的信息,包括按钮的基础信息、资源权限信息、数据权限信息

按钮资源权限信息包括忽略授权和忽略鉴权,数据权限信息包括权限标识和权限引用,设置权限标识代表需要为该按钮配置数据权限,默认情况下只能查看自己(创建人是当前用户)的数据.

数据权限

数据权限是一个单独的数据结构定义,具体包含如下属性:

  • ID 没有实际意义,用于服务框架的通用增删改查
  • 权限名称 权限的对应名称 一般与按钮名称一致
  • 菜单ID 按钮对应的菜单ID
  • 按钮ID 按钮的ID
  • 请求方法 该按钮对应的请求方法
  • 请求URL 该按钮对应的请求URL
  • 权限动作 表示数据权限的标识,也称Action,在数据权限配置时使用该权限动作,唯一
  • 权限引用 用来表达同样的数据权限,方便复用,值为对应的权限动作值

请求URL和请求方法是针对WEB系统的设计,在查找数据权限定义时通过请求URL+请求方法来定位数据权限,这是用户驱动(用户在界面点击按钮)的情况,有时需要内部系统的驱动,就需要通过权限动作来定位数据权限。

委托

数据权限的设置是基于资源权限的基础上设置,即先拥有资源数据权限才能配置数据权限

按钮与数据权限定义是一对一的关系,Action是数据权限的唯一标识,通过Action来定位数据权限后,就可以匹配用户相关的委托,具体包含:

  • 用户委托 通过用户直接进行委托
  • 用户组委托 通过用户组进行委托,用户组内的用户都拥有对应的委托
  • 职位委托 通过职位进行委托,具体查看《权限系统设计-职位设计》章节,职位对应的用户都拥有该委托,注意职位委托不区分功能,针对所有功能

委托是数据权限的一个概念(作者根据自己的理解起的名字),简述为:能看到那些用户的数据,比如看到张三的数据,可描述为:委托张三,也称为人员委托 ;如果能看到整个部门所有人的数据,则委托部门ID,也称为组织委托 系统根据委托信息来进行SQL拼接,从而达到数据权限过滤的目的。

具体如下:

数据权限的配置最终体现在对应的用户上,体现在用户在某个功能上能看到哪些数据或操作哪些数据!

从图上我们总结为:

  • 角色是数据权限过滤的第一道阀门,没有角色授权,就没有数据权限设置
  • 数据权限有三个维度的设置:用户维度、用户组维度及职位维度,用户维度和用户组维度可针对特定的功能
  • 数据权限设置分为三个维度:功能数据权限,通过委托的维度设置权限,即用户能看到哪些委托的数据;业务数据权限,通过解析SQL后列出对应的表和列信息,可通过条件构造器自定义配置表列对应的条件,从而达到灵活构建数据权限的目的;列数据权限,该数据权限只针对SELECT查询,通过不允许哪些列达到过滤列权限的目的。

一个简单的配置例子为:

java 复制代码
@Action(value = "ORDER_SEARCH")
@ActionConnect(value = {"selectList","selectCount"})
  • @Action表示权限动作,其值为ORDER_SEARCH
  • @ActionConnect为权限链接,表示数据权限作用于那个mapper(Mybatis的Mapper)

通过此配置后,执行方法会拦截获取对应的权限动作,通过获取的当前用户信息,权限动作查找用户委托、用户组委托、职位委托,汇总委托信息后进行存储,通过配置的用户委托列(默认为创建人)、组织委托列(默认为组织ID)来构建委托SQL,同时根据配置的业务数据权限来构建业务权限SQL,根据配置的列数据权限来构建排除列SQL,最终汇总成需要追加的SQL。

@Action和@ActionConnect还有更详细的配置,比如不同的用户针对不同的表列字段,有些用户需要忽略分公司权限,有些用户只过滤分公司权限;有些用户 这个有些又可以通过用户的自定义Tag来进行定义,更详细信息在后续数据权限章节详述。

总结

本章我们详细讲述了角色资源的设计,其中包括部分的数据权限设计,有什么问题再评论区留言一起探讨吧!

相关推荐
不一样的少年_1 分钟前
修了 Bug、做了重构,为什么老板还是觉得你没产出?
前端·后端·程序员
水深火乐20 分钟前
安全地生成验证码、密码和 Token
后端
小强198833 分钟前
SQL Server 慢查询怎么定位?一套从“卡”到“快”的完整排查流程
后端
水深火乐34 分钟前
interface和any
后端
步行cgn36 分钟前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端
神奇小汤圆38 分钟前
Spring Boot + LangChain4j实现RAG——从零搭建企业级知识库问答系统
后端
H_Peak43 分钟前
Python运算符与流程控制:if条件判断
后端
H_Peak1 小时前
Python字符串操作:从基础到正则入门
后端
自进化Agent智能体1 小时前
Hermes 子代理委派 —— 并行工作的艺术
后端
步行cgn1 小时前
MyBatis 动态 SQL 中的 <foreach> 标签完全解析
后端