热点





SaaS 系统如何处理一个账号对应多个角色,权限设计可以这样规划

发表时间: 2026-09-27 14:00:02   人气:80 次   

一个 SaaS 系统发展到一定规模以后,“一个用户到底是什么角色”往往会变成一个比想象中复杂的问题。

最简单的系统可以规定一个账号只能有一个角色,例如普通用户、编辑、管理员。但真正进入企业应用以后,同一个人可能同时承担多种工作:他可能是某个部门的负责人,同时又是项目管理员;在一个项目中拥有编辑权限,在另一个项目中却只能查看;甚至在同一个租户里,他是普通员工,在平台某个特定功能中又拥有管理权限。

如果数据库只给用户表增加一个 role 字段,这种需求很快就会把系统逼入死胡同。

更合理的做法,是把“用户是谁”和“用户能够做什么”分开。用户是身份主体,角色是权限集合,权限描述可以执行什么操作,而资源范围决定这些权限究竟可以作用于哪些数据。

一个账号为什么需要多个角色

假设一家企业使用 SaaS 系统,张三属于销售部门,同时负责一个项目。

在公司层面,他可能是“销售主管”;在项目层面,他又是“项目管理员”;对于财务模块,他可能只有查看权限。

如果系统只允许一个角色,就必须创建一个类似“销售主管+项目管理员+财务查看”的超级角色。

问题在于,这种角色会越来越多。

李四可能是销售主管加项目成员,王五可能是销售主管加财务管理员。几个月以后,系统里就会出现大量针对个人组合出来的角色。

这就是权限设计经常出现的“角色爆炸”。

因此,一个成熟的 SaaS 系统通常允许用户与多个角色建立关联。用户拥有多个角色后,系统再根据这些角色对应的权限计算当前请求是否允许执行。

用户、租户、角色和权限不能混在一起

多租户 SaaS 最容易犯的错误,就是把“用户是管理员”理解成一个全局属性。

实际上,一个用户可能属于多个租户,也可能在不同租户中拥有完全不同的角色。

例如同一个账号加入公司 A 后是普通员工,加入公司 B 后却是管理员。

因此,角色关系通常不能简单设计成:

user_id → role_id

而应该至少考虑租户或者组织上下文。

一个常见设计是使用用户、租户、角色和用户角色关联等数据结构。例如用户表保存账号身份,租户表保存企业或组织,角色表保存角色定义,用户角色关联表保存“哪个用户在什么租户中拥有哪个角色”。

这样,系统判断权限时首先确定当前请求属于哪个租户,然后再判断这个用户在这个租户中拥有哪些角色。

这一步非常重要,因为“管理员”不是一个脱离上下文的绝对身份。

RBAC 是基础,但不要把所有问题都塞进角色

对于绝大多数 SaaS 系统,RBAC,也就是基于角色的访问控制,是一个非常合适的基础模型。

角色可以定义成:

管理员可以管理用户;

编辑可以创建和修改文章;

审核员可以审核文章;

普通用户可以查看文章。

权限则可以进一步拆分成资源和操作。

例如:

article.read

article.create

article.update

article.delete

article.publish

这样,角色只是这些权限的集合。

“编辑”角色可以拥有 article.read、article.create 和 article.update;“审核员”可以拥有 article.read 和 article.publish。

这种设计比在程序代码中到处写:

if ($user->role == 'admin')

更加容易维护。

但 RBAC 解决的是“用户有没有某种能力”,并不自动解决“他可以操作哪一条数据”。

真正复杂的是数据范围

假设张三拥有 article.update 权限。

这是否意味着他可以修改整个 SaaS 平台所有租户的文章?

当然不是。

即使张三拥有编辑权限,也可能只能修改自己部门的文章,或者只能修改自己创建的文章。

因此,权限判断至少需要区分两个层面。

第一层是操作权限,也就是“能不能修改文章”。

第二层是资源范围,也就是“能修改哪些文章”。

例如一个角色可以拥有文章编辑权限,但数据范围限制为当前租户;另一个角色则只能操作自己创建的文章。

这也是为什么 SaaS 权限系统不能只依赖 RBAC。

当权限开始受到部门、地区、项目、资源所有者、组织层级等条件影响时,就需要加入更加细粒度的授权规则。这个时候可以采用 RBAC 与属性或策略条件结合的方式,而不一定需要把整个系统改造成一个复杂的 ABAC 策略引擎。

多个角色的权限通常应该怎么合并

假设一个用户同时拥有“编辑”和“审核员”两个角色。

编辑拥有:

article.read

article.create

article.update

审核员拥有:

article.read

article.publish

那么这个用户最终拥有的有效权限通常就是两个角色权限的集合。

也就是说,多个角色产生的是权限叠加,而不是角色之间互相覆盖。

因此,一般不需要人为给角色设置“管理员优先级100、编辑优先级50”这种机制来决定谁覆盖谁。

真正需要定义的是权限冲突规则。

例如一个角色允许访问某项资源,而另一个角色明确拒绝访问,系统到底采用允许还是拒绝?

这不能靠“哪个角色等级高”简单解决,而应该在整个授权模型建立统一规则。

一种常见做法是明确规定拒绝优先;另一种更简单的 RBAC 系统则尽量避免在角色层面设置显式 deny,只通过授予哪些权限来控制访问。

关键是规则必须稳定、可预测,而且所有业务模块都使用同一套授权逻辑。

角色继承也不要设计得太复杂

角色继承听起来很方便。

例如“管理员”继承“编辑”,于是管理员自动拥有编辑权限。

但角色层级一旦过深,权限关系就会变得很难理解。

管理员继承编辑,编辑继承普通用户,项目管理员又继承编辑,最后某个用户到底为什么拥有某项权限,开发人员甚至需要沿着多层继承关系才能查出来。

因此,对于大多数 SaaS 系统,角色继承应该保持简单。

如果只是为了减少重复权限,可以让高级角色包含基础角色的权限;但不要轻易建立几十层复杂的继承树。

更进一步的系统甚至可以不使用传统的角色继承,而是通过角色组合来解决权限复用问题。

权限模型最怕的并不是代码多,而是管理员自己都无法解释“为什么这个人拥有这个权限”。

不要把权限直接写死在前端

前端可以根据权限隐藏按钮,但这只是用户界面控制,不是安全控制。

例如页面上没有“删除用户”按钮,并不意味着用户没有删除用户的能力。

攻击者完全可以直接调用 API。

因此真正的权限检查必须发生在服务器端。

用户发送一个删除请求以后,后端需要重新确认身份、当前租户、目标资源以及操作权限。

例如用户拥有 user.delete,并不代表他可以删除另一个租户的用户。

后端必须同时验证目标用户是否属于当前租户,以及当前操作者是否有权处理这个资源。

这实际上也是防止 IDOR,也就是通过修改资源 ID 越权访问其他数据的重要措施。

权限缓存可以提高性能,但不能破坏权限一致性

大型 SaaS 系统每一次 API 请求都查询几十张权限表,当然会产生性能问题,因此权限结果经常需要缓存。

例如系统可以缓存某个用户在某个租户中的有效权限集合。

但权限缓存最大的风险就是“权限已经修改,而缓存还没有失效”。

管理员刚刚取消了某个用户的删除权限,如果旧权限还在缓存中,这个用户可能在一段时间内继续执行删除操作。

因此权限缓存必须设计明确的失效机制。

角色变化、用户角色关系变化、权限策略变化以后,应当及时使相关缓存失效。

对于高风险操作,还可以采用更加严格的实时检查,而不是完全依赖长时间缓存。

数据库设计应该保持清晰

一个基础的多角色 SaaS 权限系统,可以从这些核心数据开始设计:

users 保存用户身份。

tenants 保存企业或组织。

roles 保存角色。

permissions 保存系统权限。

user_roles 保存用户、租户与角色之间的关联。

role_permissions 保存角色与权限之间的关联。

业务数据表则根据具体业务增加 tenant_id、owner_id、department_id、project_id 等字段,用于确定资源属于谁。

这样,系统就能够分别回答几个不同的问题:

这个人是谁?

他属于哪个租户?

他在这个租户中是什么角色?

这个角色拥有哪个操作权限?

当前目标资源属于哪个租户?

这个用户是否有权对这条资源执行这个操作?

这几个问题分开以后,权限系统才容易继续扩展。

平台管理员和租户管理员必须分开

SaaS 系统还有一个经常被忽略的问题,就是平台管理员。

平台运营人员和客户企业管理员并不是同一种身份。

例如 SaaS 平台工作人员可能需要管理所有租户,而某家公司自己的管理员只能管理本公司的用户。

如果把两者都简单叫做 admin,后续很容易出现严重的权限边界问题。

因此最好明确区分平台级权限和租户级权限。

平台管理员拥有的是平台管理能力;租户管理员拥有的是当前租户范围内的管理能力。

即使某个租户管理员拥有“用户删除”权限,也不能因为 API 中存在 user_id 就允许他删除其他租户的用户。

权限系统一定要有审计记录

权限本身是安全敏感数据,因此角色和权限发生变化以后,最好留下完整的审计记录。

例如谁修改了谁的角色、什么时候修改、从什么角色改成什么角色、操作者属于哪个租户、修改了什么权限。

对于高风险操作,还应该记录具体资源和操作结果。

这样发生安全事件以后,系统才能回答一个非常现实的问题:

“这个人为什么在昨天晚上突然获得了管理员权限?”

如果没有审计日志,很多时候只能去翻服务器日志,甚至无法确定是谁做的。

不要为了“高级”而过度设计权限系统

SaaS 权限设计有一个很明显的误区,就是一开始就准备 RBAC、ABAC、策略引擎、角色继承、动态表达式、条件权限和复杂权限缓存。

结果系统还没有几个用户,权限代码已经比业务代码复杂。

更实际的路线通常是先建立清晰的 RBAC 基础,让用户可以在不同租户中拥有一个或多个角色,再增加资源范围控制。

当业务确实出现“同一个角色在不同部门权限不同”“只能操作自己创建的数据”“只能访问指定项目”等需求以后,再增加条件授权。

对于多数 SaaS 系统来说,一个结构清楚的 RBAC 加租户隔离,再结合资源级授权,就已经可以覆盖大量实际场景。

权限系统真正难的地方,不是把数据库表设计得多么复杂,而是让每一次授权判断都能够回答清楚三个问题:谁在什么租户中,以什么身份,对哪一个资源,执行什么操作。

一旦这几个概念在架构层面被明确下来,一个账号拥有多个角色就不再是特殊情况,而只是用户与角色之间多对多关系的一种正常表现。真正需要防止的,是角色、租户和数据范围彼此混杂,让一个看似普通的“管理员权限”最终变成跨租户访问数据的漏洞。

分享 Facebook | X | Whatsapp | Linkedin

捐助(Paypal): https://www.paypal.me/observeccp
订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP

责任编辑:雨轩  来源:中国观察  转载请注明作者、出处並保持完整。



今日热点:
更多新闻...
近期焦点:
最新视频

推荐阅读:


更多推荐文章:


相关新闻


更多新闻


推荐文章

伊朗经济战正在改变能源市场 下一轮油价与通胀行情会从哪里爆发

美国对伊朗发动新一轮经济攻势之后,华尔街真正需要重新计算的已经不是伊朗还能卖多少石油,而是这些石油还能不能顺利进入国际市场,以及一旦供应链进一步收缩,全...

2026年8月30日   28226

美股再创历史新高!标普500逼近7800点,AI狂潮还能走多远?

华尔街又站上了一个新的历史高点。 8月13日,美国股市延续强势,标普500指数上涨0.65%,收于7,798.99点,盘中距离7800点大关仅...

2026年8月13日   22682

查非法投票为何遭法院叫停 川普政府与左派司法体系的权力之争

发表:2026-10-22 20:37:16 | 更新:2026-10-22 20:37:16  人气: 11488

查非法投票为何遭法院叫停 川普政府与左派司法体系的权力之争

本文由中国观察編輯部原创。为了促进信息自由传播,本平台原创内容全面开放转载,无须申请授权,只需注明来源、保留原文链接,即可全文转载、引用、翻译。我们不追究版权,只在乎公正的传播。

捐助(Paypal): https://www.paypal.me/observeccp
订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP

最近文章:
更多文章...


近期要闻:
更多新闻...

编辑推荐文章:

最新发表   ⏬
更多文章...
疫情