核心概念解析:用户、角色、权限、会话

搞RBAC设计,绕不开这四个东西:用户、角色、权限、会话。很多人以为自己懂了,结果一落地就乱套。

我个人习惯先理清定义,再看它们怎么串起来。咱们一个一个拆。

用户(User)—— 系统里的「谁」

用户就是登录系统的那个人或服务。你想想看,一个电商平台,张三、李四、客服机器人、第三方支付网关,都是用户。

  • 人:有登录凭证,比如手机号、密码或人脸。
  • 服务:通过 或 JWT 代表自己。
  • 设备:比如 IoT 节点、自助终端。
我的经验:永远别把用户直接绑权限。我见过一个项目,项目经理给每个用户手动勾选「可删除订单」「可查看报表」……三个月后,客户说“新来的运营没有这个权限”,排查了一整天。后来全改成角色了。

角色(Role)—— 权限的「容器」

角色就是一组权限的集合。它抽象了“某类人应该能干什么”。

比如「运营专员」角色可以:查看订单、导出报表、修改商品描述。
「运营主管」角色多一个:审核退款、分配任务。

角色可以继承。我记得一次设计:把「基础角色」作为父类,子角色只加差异项。这样维护起来清清爽爽。

角色名称包含权限示例可分配给哪些用户
访客浏览商品、搜索未登录用户
普通用户下单、查看订单注册用户
运营专员管理商品、导出报表公司内部运营人员
管理员所有权限系统维护团队

权限(Permission)—— 最细粒度的「操作」

权限描述“能不能对某个资源做什么”。通常拆成两部分:

  • 资源:订单、商品、用户资料
  • 操作:创建、读取、更新、删除(CRUD)

举个例子:order:read 表示“读取订单”,order:create 表示“创建订单”。

我建议大家按 资源:操作 的命名规范做,别自由发挥。曾经有个项目用 can_delete_order、order_delete_right 混着写,后期做审计脚本写到怀疑人生。

权限本身不直接给人,而是挂到角色上。这是 RBAC 的核心思想。

会话(Session)—— 临时的「执行上下文」

会话就是用户登录后,系统为他创建的一个临时的、可撤销的「令牌」。它把用户、角色和权限绑定在一起,并且加了一个有效期。

很多人忽略会话,觉得就是。实际上会话管理做不好,权限全白搭。

  • 会话包含:用户ID、激活的角色列表(一个用户可能有多个角色,会话里决定用哪个)
  • 会话随时可以被终止:用户登出、管理员踢人、超时
  • 权限检查都基于会话中的角色,而不是直接从用户身上拿
避坑指南:我曾经把角色直接存在客户端JWT里,以为安全。结果某次泄密攻击,攻击者伪造JWT里的角色字段,直接拿到了管理员权限。后来改成:JWT只存 sessionId,服务端用 Redis 查真实角色。不要信任客户端传来的任何权限信息。

它们的关系 —— 一张图说清楚

RBAC 核心概念关系图 用户 User 会话 Session 角色 Role 权限 Permission 登录创建 会话激活角色 角色包含权限 一对多分配(静态) 说明:用户登录后创建会话,会话选择角色,角色承载权限。权限检查始终基于会话中的当前角色。

看这张图就容易理解了:用户登录时系统创建一个会话,会话里指定了当前激活的角色(可能有多个),角色下挂载权限。系统做鉴权时,只看会话中的角色权限集合,不会直接查用户表。

关键原则:用户不直接拥有权限,用户通过角色获得权限,角色通过会话激活。会话是运行时唯一的权限信息来源。

实际落地时需要注意的点

  1. 一个用户可以有多个角色:比如张三既是「运营专员」又是「测试用户」。会话时需要决定用哪个角色,或启用角色组后取并集。
  2. 角色不要太多:我见过一个系统建了200个角色,管理员配角色时自己都晕。一般不超过20个,够用就行。
  3. 权限要避免过于细碎:如果每个按钮都是一个权限,角色维护成本会爆炸。建议以“功能模块”为单位,比如“订单管理”是一个权限,里面包含增删改查。
  4. 会话生命周期要可控:短则15分钟,长则1天。记得给运维留一个“强制踢出所有会话”的接口,万一泄露能快速止血。
最后提醒一句:RBAC不是万能药。如果你的业务里权限判断需要根据数据状态(比如“只能删除自己创建的订单”),那纯RBAC不够,得加上ABAC(属性访问控制)。但那是后面章节的事了,咱们先把基础打牢。