4、资源树与权限点:资源目录结构设计、权限点(Permission)的定义、资源与权限的绑定
好,我们进入第四章。这一章要聊的是权限模型里最「接地气」的部分——资源树和权限点。
说白了,前面几章我们搭好了用户、角色、组织的架子。但权限最终要落到哪里?落到具体的功能按钮、数据条目、API接口上。这些东西怎么组织、怎么命名、怎么跟权限挂钩,就是本章要解决的问题。
我个人习惯把这一章称为「权限模型的骨架」。骨架搭歪了,后面所有策略都跑偏。
4.1 资源目录结构设计
先问一个问题:你手头有 200 个功能点,怎么把它们排整齐?
我见过不少团队,直接把功能列表平铺开,一个扁平的大数组。结果呢?权限配置页面滚动条拉不到底,运维人员配权限时眼睛都看花了。
正确的做法是——树形结构。
核心原则:资源树应该映射业务的组织方式,而不是代码的模块划分。
举个例子。一个电商后台,资源树可以这样分:
电商后台管理系统
├── 商品管理
│ ├── 商品列表
│ ├── 商品上架
│ ├── 商品编辑
│ └── 商品分类
├── 订单管理
│ ├── 订单列表
│ ├── 订单详情
│ ├── 订单发货
│ └── 退款处理
├── 用户管理
│ ├── 用户列表
│ ├── 用户详情
│ └── 用户封禁
└── 系统设置
├── 角色管理
├── 操作日志
└── 系统配置
你看,这个树有三层:模块 → 子模块 → 功能点。实际项目中,我建议最多不超过四层。太深了,配置起来反而麻烦。
我的经验:树形结构设计时,每个节点的「编码」要预留扩展位。比如用 4 位数字编码:0101 代表「商品管理-商品列表」,0102 代表「商品管理-商品上架」。这样中间插入新功能时,编码不会乱。
4.2 权限点(Permission)的定义
资源树搭好了,接下来要给每个叶子节点(也就是具体功能)打上「权限标签」。这个标签,就是权限点。
权限点怎么定义?我有一套固定的命名规范,用了好多年:
| 字段 | 说明 | 示例 |
|---|---|---|
| 权限编码 | 全局唯一,用于程序判断 | goods:list |
| 权限名称 | 中文描述,用于界面展示 | 商品列表查看 |
| 所属模块 | 关联到资源树节点 | 商品管理 |
| 权限类型 | 功能权限 / 数据权限 / 接口权限 | 功能权限 |
| 排序号 | 控制显示顺序 | 1 |
这里有个坑,我踩过。权限编码的命名风格,一定要统一。要么全小写+冒号分隔,要么全小写+点号分隔。别混用。
我曾经在一个项目里看到这样的编码:goods:list、order.detail、User_Edit。三种风格混在一起,后端做权限校验时,解析逻辑写了三套。后来重构时,我花了整整两天才统一完。
我个人推荐用 模块:子模块:操作 的格式。比如:
goods:list // 商品列表查看
goods:create // 商品新增
goods:edit // 商品编辑
goods:delete // 商品删除
order:ship // 订单发货
order:refund // 订单退款
user:ban // 用户封禁
system:role:assign // 角色分配
为什么用冒号?因为冒号在大多数编程语言里是合法的标识符字符,而且视觉上比点号更清晰。你想想看,system:role:assign 和 system.role.assign,哪个更容易一眼看出层级?
4.3 资源与权限的绑定
资源树和权限点都定义好了,接下来就是「绑定」——把权限点挂到资源树的节点上。
这里有两种绑定模式,我分别说一下:
4.3.1 显式绑定
每个资源节点直接关联一个或多个权限点。比如「商品列表」这个页面,关联 goods:list 这个权限点。用户点击菜单时,系统检查用户是否有这个权限。
// 资源节点定义示例
{
"id": "node_001",
"name": "商品列表",
"parentId": "module_goods",
"permissions": ["goods:list", "goods:export"]
}
4.3.2 隐式绑定
有些权限是「继承」来的。比如你有了「商品编辑」的权限,系统默认你也能「查看商品列表」。这种场景下,不需要显式绑定查看权限。
注意:隐式绑定虽然省事,但容易造成权限扩散。我建议只在「查看」类权限上使用,增删改操作必须显式绑定。
实际项目中,我通常采用 混合模式:
- 菜单/页面级别的资源,用显式绑定,一个节点绑 1-3 个权限点
- 按钮级别的资源,用隐式绑定,通过父级权限自动派生
- 数据级别的资源(比如只能看自己部门的订单),单独用数据权限规则处理
下面这张图,展示了资源树、权限点、角色三者之间的关系:
4.4 绑定时的常见陷阱
嗯,这里要注意几个容易翻车的地方:
- 权限点粒度过粗——一个权限点管了整个模块。结果就是,要么给太多权限,要么给太少。我建议一个权限点只对应一个操作。
- 权限点粒度过细——每个按钮都搞一个权限点。配置页面密密麻麻,运维人员直接崩溃。按钮级别的权限,用角色模板去批量处理。
- 资源树和权限点不同步——删了某个功能,但权限点还在数据库里躺着。时间久了,权限表里一堆「幽灵权限」。我习惯在发布流程里加一道检查:每次上线前,跑脚本清理无主权限点。
一个小技巧:在数据库里给权限点加一个 status 字段。0=启用,1=禁用,2=废弃。废弃的权限点不删除,只是不再出现在配置界面。这样既干净,又保留了历史数据,万一回滚还能恢复。
好了,这一章的内容就这些。资源树是骨架,权限点是血肉,绑定是连接它们的韧带。这三样东西设计好了,后面的权限继承、角色派生才能站得住脚。