前言
权限是PRD中最容易漏的部分。很多线上问题都是权限问题:越权访问、数据泄露、功能误操作。这篇给你RBAC权限模型的完整写法+5个真实案例。
一、RBAC模型3要素
RBAC(Role-Based Access Control,基于角色的访问控制)是权限管理的核心模型,由3个要素组成:
- **角色(Role):**用户的身份(如:管理员、普通用户、访客)
- **权限(Permission):**可以执行的操作(如:查看、编辑、删除、导出)
- **资源(Resource):**操作的对象(如:用户列表、订单详情、财务报表)
**核心逻辑:**用户 → 角色 → 权限 → 资源
RBAC模型的作用
- **权限管理:**通过角色管理权限,而不是直接给用户分配权限
- **灵活扩展:**新增角色或权限时,只需修改角色权限关系,不需要修改用户
- **易于维护:**权限集中管理,便于维护和审计
- **安全性:**防止越权访问,保护数据安全
RBAC模型的设计步骤
- **识别角色:**列出系统中所有可能的角色(如:管理员、普通用户、访客)
- **识别资源:**列出系统中所有需要权限控制的资源(如:用户管理、订单管理)
- **识别权限:**列出每个资源的所有操作权限(如:查看、编辑、删除)
- **设计权限矩阵:**明确每个角色对每个资源的权限(如:管理员可以增删改查,普通用户只能查看)
- **设计数据权限:**明确数据权限规则(如:普通用户只能查看自己的数据)
二、权限矩阵模板
| 资源/功能 | 管理员 | 部门负责人 | 普通用户 | 访客 |
|---|---|---|---|---|
| 用户管理 | 增删改查 | 查看本部门 | 查看自己 | - |
| 订单管理 | 增删改查 | 查看本部门 | 查看自己 | - |
| 数据导出 | ✓ | ✓(本部门) | ✗ | ✗ |
| 系统设置 | ✓ | ✗ | ✗ | ✗ |
三、5个真实案例详解
案例1:电商后台
**业务场景:**电商平台后台管理系统,需要管理商品、订单、用户、财务等模块
角色定义:
- **超级管理员:**所有权限,可以管理所有模块和用户
- **运营:**商品管理、订单管理、用户管理(查看),负责日常运营工作
- **客服:**订单管理(查看/编辑)、用户管理(查看),负责客服工作
- **财务:**订单管理(查看)、财务报表(查看/导出),负责财务工作
权限矩阵:
| 功能 | 超管 | 运营 | 客服 | 财务 |
|------|-----|------|-----|------|
| 商品上架 | ✓ | ✓ | ✗ | ✗ |
| 商品下架 | ✓ | ✓ | ✗ | ✗ |
| 商品编辑 | ✓ | ✓ | ✗ | ✗ |
| 订单查看 | ✓ | ✓ | ✓ | ✓ |
| 订单编辑 | ✓ | ✓ | ✓ | ✗ |
| 订单退款 | ✓ | ✓ | ✓ | ✗ |
| 用户查看 | ✓ | ✓ | ✓ | ✗ |
| 用户编辑 | ✓ | ✓ | ✗ | ✗ |
| 用户禁用 | ✓ | ✓ | ✗ | ✗ |
| 财务报表查看 | ✓ | ✗ | ✗ | ✓ |
| 财务报表导出 | ✓ | ✗ | ✗ | ✓ |
| 系统设置 | ✓ | ✗ | ✗ | ✗ |
数据权限:
- 超管:全量数据
- 运营:全量数据(商品、订单、用户)
- 客服:全量订单数据,只能查看用户数据
- 财务:全量订单数据,只能查看财务数据
PRD写法:
电商后台权限设计:
【角色列表】
1. 超级管理员:所有权限,可以管理所有模块和用户
2. 运营:商品管理、订单管理、用户管理(查看)
3. 客服:订单管理(查看/编辑)、用户管理(查看)
4. 财务:订单管理(查看)、财务报表(查看/导出)
【权限矩阵】
见上表
【数据权限】
- 超管:全量数据
- 运营:全量数据(商品、订单、用户)
- 客服:全量订单数据,只能查看用户数据
- 财务:全量订单数据,只能查看财务数据
【权限校验点】
- 页面级:无权限时跳转403页面
- 按钮级:无权限时隐藏按钮
- 接口级:无权限时返回403错误
- 字段级:敏感字段(如手机号)脱敏显示
案例2:CRM系统
**业务场景:**客户关系管理系统,需要管理客户、销售机会、合同等数据
角色定义:
- **销售总监:**查看全部客户、全部销售机会,负责整体销售管理
- **销售经理:**查看本团队客户、本团队销售机会,负责团队管理
- **销售:**查看自己的客户、自己的销售机会,负责具体销售工作
- **售前:**查看全部客户(只读),负责售前支持
权限矩阵:
| 功能 | 销售总监 | 销售经理 | 销售 | 售前 |
|------|---------|---------|-----|------|
| 客户查看 | ✓(全部) | ✓(本团队) | ✓(自己的) | ✓(全部,只读) |
| 客户编辑 | ✓ | ✓(本团队) | ✓(自己的) | ✗ |
| 销售机会查看 | ✓(全部) | ✓(本团队) | ✓(自己的) | ✗ |
| 销售机会编辑 | ✓ | ✓(本团队) | ✓(自己的) | ✗ |
| 合同查看 | ✓(全部) | ✓(本团队) | ✓(自己的) | ✗ |
| 合同编辑 | ✓ | ✓(本团队) | ✓(自己的) | ✗ |
数据权限:
- 销售总监:全量数据(WHERE 1=1)
- 销售经理:team_id = 当前用户team_id
- 销售:owner_id = 当前用户id
- 售前:全量数据(只读,WHERE 1=1)
案例3:项目管理系统
**业务场景:**项目管理系统,需要管理项目、任务、需求等
角色定义:
- **项目经理:**项目全部权限,负责项目管理
- **开发:**任务查看/编辑(自己负责的),负责开发工作
- **测试:**任务查看/编辑(自己负责的),负责测试工作
- **产品:**需求查看/编辑,负责产品工作
权限矩阵:
| 功能 | 项目经理 | 开发 | 测试 | 产品 |
|------|---------|-----|------|------|
| 创建项目 | ✓ | ✗ | ✗ | ✗ |
| 编辑项目 | ✓ | ✗ | ✗ | ✗ |
| 删除项目 | ✓ | ✗ | ✗ | ✗ |
| 分配任务 | ✓ | ✗ | ✗ | ✗ |
| 查看任务 | ✓(全部) | ✓(自己的) | ✓(自己的) | ✓(全部) |
| 更新任务 | ✓(全部) | ✓(自己的) | ✓(自己的) | ✗ |
| 创建需求 | ✓ | ✗ | ✗ | ✓ |
| 编辑需求 | ✓ | ✗ | ✗ | ✓ |
| 查看需求 | ✓(全部) | ✓(全部) | ✓(全部) | ✓(全部) |
数据权限:
- 项目经理:项目内全量数据(WHERE project_id = 当前用户project_id)
- 开发:项目内自己的任务(WHERE project_id = 当前用户project_id AND owner_id = 当前用户id)
- 测试:项目内自己的任务(WHERE project_id = 当前用户project_id AND owner_id = 当前用户id)
- 产品:项目内全量需求(WHERE project_id = 当前用户project_id)
案例4:内容管理系统
**业务场景:**内容管理系统,需要管理文章、视频等内容
角色定义:
- **超级管理员:**所有权限,可以管理所有内容和用户
- **编辑:**内容创建/编辑/提交审核,负责内容编辑
- **审核员:**内容审核/发布/下架,负责内容审核
- **作者:**内容创建/编辑(自己的),负责内容创作
权限矩阵:
| 功能 | 超管 | 编辑 | 审核员 | 作者 |
|------|-----|------|-------|------|
| 内容创建 | ✓ | ✓ | ✗ | ✓ |
| 内容编辑 | ✓(全部) | ✓(全部) | ✗ | ✓(自己的) |
| 内容删除 | ✓ | ✗ | ✗ | ✓(自己的,草稿状态) |
| 提交审核 | ✓ | ✓ | ✗ | ✓(自己的) |
| 审核通过 | ✓ | ✗ | ✓ | ✗ |
| 审核驳回 | ✓ | ✗ | ✓ | ✗ |
| 发布 | ✓ | ✗ | ✓ | ✗ |
| 下架 | ✓ | ✗ | ✓ | ✗ |
状态与权限:
- 草稿:作者可编辑/删除,编辑可编辑,审核员可查看
- 待审核:审核员可审核/驳回,编辑可查看,作者可查看
- 已发布:审核员可下架,编辑可查看,作者可查看
- 已下架:审核员可重新发布,编辑可查看,作者可查看
案例5:SaaS多租户系统
**业务场景:**SaaS多租户系统,需要实现数据隔离和权限管理
角色定义:
- **平台管理员:**管理所有租户,负责平台管理
- **租户管理员:**管理本租户所有数据,负责租户管理
- **租户普通用户:**查看本租户数据(受数据权限限制),负责日常使用
权限矩阵:
| 功能 | 平台管理员 | 租户管理员 | 租户普通用户 |
|------|----------|----------|------------|
| 租户管理 | ✓ | ✗ | ✗ |
| 用户管理 | ✓(全部) | ✓(本租户) | ✗ |
| 数据查看 | ✓(全部) | ✓(本租户) | ✓(本租户,受数据权限限制) |
| 数据编辑 | ✓(全部) | ✓(本租户) | ✓(本租户,受数据权限限制) |
| 数据删除 | ✓(全部) | ✓(本租户) | ✗ |
| 系统设置 | ✓ | ✓(本租户) | ✗ |
数据隔离:
- 所有数据必须带tenant_id
- 查询时自动过滤:WHERE tenant_id = 当前用户tenant_id
- 跨租户访问:403 Forbidden
- 平台管理员:可以查看所有租户数据(WHERE 1=1)
数据隔离实现:
// 伪代码
function queryData(table, conditions) {
const user = getCurrentUser();
// 平台管理员可以查看所有租户数据
if (user.role === 'platform_admin') {
return db.query(`SELECT * FROM ${table} WHERE ${conditions}`);
}
// 其他用户只能查看本租户数据
return db.query(`SELECT * FROM ${table} WHERE tenant_id = ? AND ${conditions}`, [user.tenant_id]);
}
四、PRD写法模板与最佳实践
标准PRD模板
权限设计:
【角色列表】
1. 管理员:所有权限,可以管理所有模块和用户
2. 普通用户:查看自己的数据,编辑自己的数据
3. 访客:只能查看公开数据
【权限矩阵】
| 资源/功能 | 管理员 | 普通用户 | 访客 |
|----------|-------|---------|------|
| 用户管理 | 增删改查 | 查看自己 | - |
| 订单管理 | 增删改查 | 查看自己 | - |
| 数据导出 | ✓ | ✗ | ✗ |
| 系统设置 | ✓ | ✗ | ✗ |
【数据权限】
- 管理员:全量数据(WHERE 1=1)
- 普通用户:owner_id = 当前用户id(WHERE owner_id = ?)
- 访客:公开数据(WHERE is_public = 1)
【权限校验点】
1. 页面级:无权限时跳转403页面
2. 按钮级:无权限时隐藏按钮(v-if="hasPermission('edit')")
3. 接口级:无权限时返回403错误(HTTP 403 Forbidden)
4. 字段级:敏感字段脱敏显示(如手机号:138****8888)
【权限实现方式】
1. 前端权限控制:
- 路由守卫:检查用户权限,无权限跳转403
- 按钮权限:v-if="hasPermission('edit')"
- 菜单权限:根据用户权限动态生成菜单
2. 后端权限控制:
- 接口权限:每个接口检查用户权限
- 数据权限:查询时自动过滤数据(WHERE owner_id = ?)
- 字段权限:返回数据时过滤敏感字段
【权限缓存】
- 用户登录时,缓存用户角色和权限
- 权限变更时,清除缓存,重新加载
最佳实践
- 角色设计:
- 角色数量控制在10个以内,过多会导致复杂度增加
- 使用系统角色+业务角色的方式(如:管理员+销售、客服)
- 角色命名清晰,避免歧义
- 权限设计:
- 权限粒度适中,不要过细(如:查看、编辑、删除)
- 使用资源+操作的组合(如:user:view、user:edit、user:delete)
- 权限命名规范,便于管理和维护
- 数据权限:
- 明确数据权限规则(如:owner_id = 当前用户id)
- 查询时自动过滤数据,避免越权访问
- 敏感数据脱敏显示(如手机号、身份证号)
- 权限校验:
- 前端和后端都要做权限校验,不能只依赖前端
- 权限校验要统一,避免重复代码
- 权限变更要及时更新缓存
- 权限审计:
- 记录所有权限操作(谁、何时、操作了什么)
- 定期审计权限使用情况,发现异常及时处理
实现检查清单
-
\] 角色列表完整(所有可能的角色都已列出)
-
\] 数据权限明确(数据权限规则清晰)
-
\] 前端权限控制(路由守卫、按钮权限、菜单权限)
-
\] 权限缓存机制(用户登录时缓存,权限变更时清除)
五、常见错误与陷阱
错误1:角色设计不合理
**问题:**角色数量过多或角色定义不清晰,导致权限管理混乱。
❌ 错误示例:
角色:管理员、超级管理员、系统管理员、运营管理员、商品管理员、订单管理员...
问题:角色太多,难以管理和维护
✅ 正确示例:
系统角色:超级管理员、管理员
业务角色:运营、客服、财务
使用角色组合:管理员+运营、管理员+客服
错误2:权限粒度不合理
**问题:**权限粒度过细或过粗,导致权限管理困难。
❌ 错误示例:
权限:查看用户列表、查看用户详情、编辑用户姓名、编辑用户邮箱、编辑用户手机号...
问题:权限粒度过细,难以管理
✅ 正确示例:
权限:user:view(查看用户)、user:edit(编辑用户)、user:delete(删除用户)
使用资源+操作的组合,粒度适中
错误3:数据权限不明确
**问题:**没有明确数据权限规则,导致越权访问。
❌ 错误示例:
普通用户可以查看所有订单
问题:数据权限不明确,可能导致数据泄露
✅ 正确示例:
普通用户只能查看自己的订单(WHERE owner_id = 当前用户id)
数据权限规则明确,防止越权访问
错误4:只做前端权限控制
**问题:**只在前端做权限控制,后端没有做权限校验,导致安全漏洞。
❌ 错误示例:
前端:v-if="hasPermission('edit')"(隐藏编辑按钮)
后端:没有权限校验,直接允许编辑
问题:用户可以通过接口直接编辑,绕过前端权限控制
✅ 正确示例:
前端:v-if="hasPermission('edit')"(隐藏编辑按钮)
后端:接口中检查权限,无权限返回403
前后端都要做权限校验,不能只依赖前端
错误5:权限缓存不及时更新
**问题:**权限变更后,缓存没有及时更新,导致权限不生效。
❌ 错误示例:
用户权限变更后,缓存没有清除
问题:用户仍然使用旧权限,新权限不生效
✅ 正确示例:
用户权限变更后,立即清除缓存,重新加载
权限变更时,通知所有相关用户重新登录或刷新权限
错误6:权限审计不完善
**问题:**没有记录权限操作日志,导致问题排查困难。
❌ 错误示例:
没有记录权限操作日志
问题:无法追溯权限变更历史,问题排查困难
✅ 正确示例:
记录所有权限操作:
- 操作人:谁执行的操作
- 操作时间:何时执行的操作
- 操作类型:权限分配、权限回收、角色变更
- 操作内容:具体操作了什么
- 操作IP:操作时的IP地址
六、FAQ
Q1:角色太多怎么办?
**答:**建议分组:系统角色(超管/管理员)+ 业务角色(销售/客服/财务)。
方案1:角色分组
- 系统角色:超级管理员、管理员
- 业务角色:运营、客服、财务、销售
方案2:角色组合
- 一个用户可以有多个角色(如:管理员+运营)
- 权限取并集(拥有所有角色的权限)
Q2:一个用户可以有多个角色吗?
**答:**可以。权限取并集(拥有所有角色的权限)。
实现方式:
- 用户可以有多个角色(如:管理员+运营)
- 权限取并集:用户拥有所有角色的权限
- 如果角色权限冲突,取权限更大的(如:编辑权限包含查看权限)
示例:
- 用户A:管理员角色(所有权限)+ 运营角色(商品管理、订单管理)
- 用户A的权限:所有权限(管理员权限)
Q3:如何设计数据权限?
**答:**根据业务需求设计数据权限规则。
常见数据权限规则:
- **全量数据:**WHERE 1=1(管理员)
- **部门数据:**WHERE department_id = 当前用户department_id(部门负责人)
- **团队数据:**WHERE team_id = 当前用户team_id(团队负责人)
- **自己的数据:**WHERE owner_id = 当前用户id(普通用户)
实现方式:
- 查询时自动过滤数据(WHERE条件)
- 使用数据权限中间件,统一处理数据权限
- 敏感数据脱敏显示(如手机号、身份证号)
Q4:如何实现权限控制?
**答:**前端和后端都要做权限控制。
前端权限控制:
- 路由守卫:检查用户权限,无权限跳转403
- 按钮权限:v-if="hasPermission('edit')"
- 菜单权限:根据用户权限动态生成菜单
后端权限控制:
- 接口权限:每个接口检查用户权限
- 数据权限:查询时自动过滤数据
- 字段权限:返回数据时过滤敏感字段
Q5:如何测试权限?
**答:**测试以下场景:
- **正常权限:**测试有权限的用户可以正常访问
- **无权限访问:**测试无权限的用户不能访问(应该返回403)
- **越权访问:**测试用户不能访问其他用户的数据(应该返回403)
- **权限变更:**测试权限变更后,用户权限是否正确更新
Q6:如何优化权限性能?
**答:**可以从以下方面优化:
- **权限缓存:**用户登录时缓存用户角色和权限,减少数据库查询
- **权限预加载:**页面加载时预加载权限,减少接口调用
- **权限索引:**数据库中添加权限相关索引,提高查询性能
- **权限批量查询:**批量查询用户权限,减少数据库查询次数