tech-org-scoped-role-permission.md 2.8 KB

组织上下文角色权限模型

来源:变更 org-scoped-role-permission 时间:2026-07-06

问题描述

旧权限模型只有 tenant_id + user_id + role_id 的全局用户角色关系,无法表达同一账号在同一数据中心下多个组织拥有不同角色。放开多组织后,如果仍按用户全部组织计算角色、菜单、API 和数据权限,会造成组织间串权。

解决方案

上下文分层

  • 数据中心是第一层上下文,继续使用现有 tenantIdsys_user_tenant/system/tenant/switch
  • 组织是第二层上下文,使用 LoginUser.activeOrgId 表示当前请求的唯一组织。
  • LoginUser.orgIds 只表示可切换组织集合,不表示一次请求的数据权限范围。

授权模型

  • 用户组织成员关系仍由 sys_user_org 表达。
  • 角色适用组织由 sys_role_org 表达,表示角色在哪些组织可被分配。
  • 用户在组织内的真实角色授权由 sys_user_org_role 表达。
  • sys_user_role 只作为迁移和兼容来源,普通权限计算不能回退旧表。

权限计算

  • 登录、刷新用户信息、切换数据中心和切换组织后,必须按 tenantId + userId + activeOrgId 重算 roleIds/roleKeys/permissions/apiPermissions
  • ORG 数据权限只使用当前组织。
  • ORG_AND_CHILD 只展开当前组织及子组织。
  • CUSTOM 只基于当前组织有效角色的自定义范围。
  • 消息、流程、数据集等旁路不能直接读取旧 sys_user_role 或用户全部 orgIds

超级管理员边界

历史超级管理员可能没有 sys_user_org 显式绑定。为兼容老账号,登录态可以把当前数据中心全量组织作为兜底组织上下文。

但组织切换选项和切换校验不能直接相信登录态兜底 orgIds。应重新查询 sys_user_org

  • 有显式绑定时,只返回和允许切换绑定组织。
  • 没有显式绑定的历史超级管理员,才保留当前数据中心全量组织兜底。

前端组织切换器可继续用扁平下拉展示,路径文案足够承载少量组织,不需要强制树形控件。

相关文件

  • forge-server/forge-framework/forge-plugin-parent/forge-plugin-system/src/main/java/com/mdframe/forge/plugin/system/service/impl/UserLoadServiceImpl.java
  • forge-server/forge-framework/forge-plugin-parent/forge-plugin-system/src/main/java/com/mdframe/forge/plugin/system/service/impl/SysOrgServiceImpl.java
  • forge-server/forge-framework/forge-starter-parent/forge-starter-datascope/src/main/java/com/mdframe/forge/starter/datascope/service/impl/DataScopeServiceImpl.java
  • forge-server/forge-framework/forge-starter-parent/forge-starter-datascope/src/main/java/com/mdframe/forge/starter/datascope/handler/DataScopeInterceptor.java
  • forge-server/db/migration/V1.0.1__add_org_scoped_role_permission.sql