一、权限模型设计:从RBAC到ABAC,再到多租户下的权限粒度

权限模型这件事,说白了就是解决「谁能做什么」的问题。我做了这么多年权限系统,踩过的坑比走过的路还多。今天咱们就聊聊RBAC和ABAC这两个主流模型,以及多租户场景下怎么划分权限粒度。

1.1 RBAC原理:角色是权限的集合

RBAC,全称Role-Based Access Control。核心思路就是把权限打包成角色,然后把人塞进角色里。你想想看,这样就不用给每个用户单独配权限了,省事不少。

我在项目中遇到过最典型的RBAC场景就是企业办公系统。管理员、经理、普通员工,三种角色搞定所有。系统里几百号人,权限管理却只需要维护三套角色配置——这就是RBAC的魅力。

RBAC的核心概念

  • 主体(Subject):用户或用户组
  • 角色(Role):权限的逻辑集合
  • 权限(Permission):对资源的操作许可
  • 会话(Session):主体激活的角色集合

RBAC0是最基础的模型,只有用户-角色-权限三层。我记得有个项目,需求方非要加角色继承和角色约束,那就是RBAC1和RBAC2的事了。不过说实话,80%的场景用RBAC0就够了,别给自己找不痛快。

实战小建议

我一般会先画一个「主体-角色-权限」的关系表。角色别超过20个,太多就说明你的角色粒度有问题了。

1.2 ABAC原理:属性驱动的动态决策

ABAC(Attribute-Based Access Control)比RBAC灵活得多。它不靠角色,而是根据一堆属性来算你有没有权限。属性可以是用户的、资源的、环境的,甚至是上下文相关的。

举个例子:
「允许深圳分公司的工程师在工作日9:00-18:00访问销售数据,但只有销售额超过10万的客户记录才可见。」

这种场景RBAC就不好使了。你总不能为了「深圳+工程师+工作日+9-18点+销售额>10万」建一个角色吧?那角色表得炸了。

我曾经犯过的错

有一次我把ABAC的决策逻辑写死在代码里,结果业务部门三天改一次规则,每次都要改代码重新部署。后来我学乖了,把规则存到数据库里,用表达式引擎动态解析。你猜怎么着?运维同事再也不用半夜被我叫起来上线了。

对比维度 RBAC ABAC
决策依据 角色 属性组合
灵活性 中 高
维护成本 低 中高
性能 高(缓存友好) 中(需实时计算)
适用场景 稳定、角色分明 动态、条件复杂

我个人的习惯是:能用RBAC解决就别上ABAC。ABAC虽然灵活,但规则多了容易变成一团乱麻。你想想看,几百条属性规则相互影响,排查问题时脑袋都要大了。

1.3 多租户下的权限粒度划分

多租户场景有个特殊问题:权限不仅要管「谁能做什么」,还得管「在哪个租户里做」。这就涉及到权限粒度的划分了。

我记得有个SaaS项目,刚开始只分了三个粒度:系统级、租户级、用户级。结果客户越来越多,需求越来越怪。有的租户要限制某个数据表里的行级访问,有的要控制API的调用次数,有的甚至要精细到某个字段的可见性。

1.3.1 四个粒度层级

  1. 租户级粒度:整个租户的开关。比如租户A能不能使用导出功能。
  2. 模块级粒度:功能模块的访问。比如租户A的销售模块对哪些人开放。
  3. 数据级粒度:具体数据行/对象的访问。比如只允许查看自己团队的客户。
  4. 字段级粒度:数据字段的可见性。比如销售金额字段只对经理可见。

我建议的粒度划分原则

  • 静态权限用RBAC,动态条件用ABAC
  • 租户级和模块级用RBAC
  • 数据级和字段级用ABAC
  • 不要一开始就追求太细的粒度,迭代着来

1.3.2 多租户下的权限决策流程

实际执行时,我会把权限决策拆成三步:

第一步:租户身份校验
先确认请求属于哪个租户,有没有被冻结或过期。

第二步:模块级RBAC检查
用户角色有没有这个模块的访问权限?没有就直接拒绝了。

第三步:数据级/字段级ABAC过滤
通过了前两步,再根据属性规则做精细化控制。

避坑提示

我曾经遇到过一个项目,在数据级权限上用了全表扫描过滤,结果一个查询跑了十几秒。后来老老实实加了索引和缓存,还在SQL层面就做了权限约束。嗯,这里要注意——权限过滤尽量前置到数据库查询里,别在应用层一条条过滤。

多租户权限模型分层架构图 多租户权限模型分层架构 租户隔离层 租户身份识别 | 租户状态校验 | 租户级开关 RBAC 角色权限层 静态角色分配 | 模块/功能级访问控制 ABAC 属性策略层 动态属性计算 | 数据级/字段级过滤 资源访问层 API / 数据库 / 文件系统 租户级隔离 模块级控制 精细过滤

1.4 综合推荐:混合模型

讲了这么多,你可能会问:到底用RBAC还是ABAC?我的答案是——都用。

实际操作中,我推荐一种混合模型:

  • 底层权限(租户、模块):用RBAC,简单高效
  • 上层权限(数据、字段):用ABAC,灵活精确
  • 中间加一层缓存:把ABAC计算结果缓存起来,避免每次请求都重新算

这样既能享受RBAC的简洁,又能用ABAC处理复杂场景。我记得有个项目用这套方案扛住了上万条策略规则,线上运行两年没出过权限相关的事故。

最后一句掏心窝的话

权限模型没有银弹。开始做之前,先问问自己:这个系统未来三年会不会有复杂的权限需求?如果大概率没有,RBAC就够了。如果可能很复杂——比如多租户SaaS——那趁早把ABAC的架子搭好。别等到客户来投诉了才临时抱佛脚。