企业级权限系统怎么设计四 ------ ABAC模型统一功能权限与数据权限
在上一篇关于数据权限的文章中 ,我们提到了 ABAC(Attribute-Based Access Control)模型作为更灵活、通用的权限控制方式。本篇将聚焦在 ABAC 的建模与实际应用,尤其是如何统一表达功能权限与数据权限。
ABAC 的核心思想是"属性驱动决策",通过用户、资源、环境等属性来判断是否允许某操作,特别适合权限规则复杂、变化频繁的企业系统。
1. ABAC 模型增强设计
为了让 ABAC 模型兼顾功能权限与数据权限控制,我们对策略表结构进行以下扩展:
- 新增
policy_type
字段区分策略类型(function/data); - 新增
effect
字段表示策略结果(allow/deny),支持显式拒绝优先原则。
更新后的 ABAC_POLICY 表结构如下:
erDiagram
ABAC_POLICY {
int policy_id PK
varchar policy_code "策略代码,便于配置和识别"
varchar policy_name "策略名称"
varchar policy_type "策略类型 (function/data)"
varchar effect "策略效果 (allow/deny)"
varchar resource "资源标识"
varchar action "操作标识"
varchar pre_condition_expr "策略前置条件表达式"
boolean enabled "策略是否启用"
}
"...其它同原模型"
effect = deny
的策略可用于兜底控制场景,明确表达拒绝优先逻辑。
2. 功能权限场景:请假申请控制
以某企业的审批系统为例,用户是否能发起"请假申请"(功能点 leave_request.submit
)由以下条件决定:
权限判断逻辑
- 员工类型必须为正式员工(
employee_type = formal
); - 员工在职状态为有效(
employee_status = active
); - 年假剩余天数大于 0;
- 如果用户属于销售部门(
dept_code = sales
),仅允许在工作日提交申请(基于day_of_week
环境属性判断)。
💡
day_of_week
属于环境属性,可由系统在请求上下文中注入(如通过拦截器记录当前星期)。
该权限控制场景涵盖了用户属性 与环境属性的组合,是典型的 ABAC 功能权限应用。
3. 策略配置示例
策略绑定 ABAC_BINDING
用户 u002 绑定策略 p002,表明该用户适用于该请假控制策略。
subject_type | subject_id | policy_id |
---|---|---|
user | u002 | p002 |
策略定义 ABAC_POLICY
策略 p002 针对资源 leave_request
的 submit
操作生效。
policy_id | policy_code | policy_name | policy_type | effect | resource | action | pre_condition_expr | enabled |
---|---|---|---|---|---|---|---|---|
p002 | LEAVE_SUBMIT_ACCESS | 请假申请提交权限控制 | function | allow | leave_request | submit | true |
条件组 ABAC_POLICY_GROUP
定义两个条件组:
id | policy_id | group_code | name | logical_op |
---|---|---|---|---|
g101 | p002 | GRP_EMPLOY_CHECK | 员工资格检查组 | AND |
g102 | p002 | GRP_SALES_EXTRA | 销售部门附加条件组 | AND |
条件定义 ABAC_POLICY_CONDITION
g101(员工资格检查组)
id | group_id | field | operator | value_type | value_expr |
---|---|---|---|---|---|
10 | g101 | employee_type | = | const | formal |
11 | g101 | employee_status | = | const | active |
12 | g101 | annual_leave_days | const | 0 |
g102(销售部门附加条件组)
id | group_id | field | operator | value_type | value_expr |
---|---|---|---|---|---|
13 | g102 | dept_code | = | const | sales |
14 | g102 | day_of_week | NOT IN | const | (Saturday, Sunday) |
4. 功能权限和数据权限实现差异
虽然功能权限和数据权限可以共享 ABAC 统一结构,但系统实现层面,一般建议功能权限和数据权限"模型统一、执行路径分离"
对比项 | 功能权限(function) | 数据权限(data) |
---|---|---|
决策时机 | 接口层权限校验 | 数据访问阶段(构造 SQL 时) |
判断机制 | 表达式引擎(如 SpEL / Aviator / MVEL) | 策略引擎 + SQL 构造器 + 用户上下文 |
执行效率 | 高(可缓存策略判断结果) | 中(需要实时构建 WHERE 语句) |
使用场景 | 控制功能、按钮、菜单、流程是否可见/可操作 | 控制查询结果范围或数据可操作性(如可见金额上限) |
示例 | 请假发起、数据导出、审批按钮是否可点击 | 仅查询本人/本部门数据、金额小于 100 万的数据等 |
缓存建议 | ✅ 建议缓存(user + resource + action) | 🚫 不建议缓存,需依赖动态上下文构造 |
5. 小结与建议
通过引入 policy_type
与 effect
字段,ABAC 模型不仅能表达数据权限控制,还可以覆盖功能权限判断,实现权限体系的统一建模、分场景落地。
- 对于 功能权限:推荐使用表达式引擎进行快速判断,结果可缓存提升性能;
- 对于 数据权限 :需结合用户上下文动态构造 SQL,实时性要求高,不宜做缓存。
🔍 尽管 ABAC 模型强大灵活,但也不是"银弹"。是否使用 ABAC,或使用哪种策略引擎,一定要结合业务复杂度和变更频率合理决策 。简单场景下 RBAC 或数据范围方案仍更高效,避免过度设计也是业务系统落地成功的关键。