前言
权限是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:如何优化权限性能?
答:可以从以下方面优化:
- 权限缓存:用户登录时缓存用户角色和权限,减少数据库查询
- 权限预加载:页面加载时预加载权限,减少接口调用
- 权限索引:数据库中添加权限相关索引,提高查询性能
- 权限批量查询:批量查询用户权限,减少数据库查询次数
工具入口
生成RBAC权限矩阵思维导图