Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

多租户方案的优化建议,希望评估下可行性,能否在未来版本中实现 #5808

Closed
citynook opened this issue Jan 12, 2024 · 4 comments

Comments

@citynook
Copy link

citynook commented Jan 12, 2024

版本号:

3.6.2

前端版本:vue3版?还是 vue2版?

vue3

问题描述:

公司IT团队关注在业务方面,没有精力升级现有的开发平台,所以就找一些第三方开发平台来验证公司用户的各类需求,其中 JeecgBoot 功能完整度高,基本上满足公司的要求,但多租户功能尚有些欠缺,现整理出方案供参考。

此方案在 JeecgBoot 现有功能的基础上进行优化,改动并不算大,但可以将【平台管理员角色】、【租户管理员角色】的职能做一个明确的划分,在保障数据安全的前提下同时满足不同的应用场景。

一、前言

一、术语说明
1.1默认租户/平台管理租户:系统自带一个租户ID等于0的租户,在单租户模式下,可视为默认租户;在多租户模式下,此租户将做为平台管理租户。
1.2普通租户:在多租户模式下,由【平台管理租户】创建的租户均视为普通租户。

1.3平台管理员角色:负责对所有租户的管理,包括:创建、修改、删除,分配套餐(分派菜单)等。平台管理员没有权限访问租户的配置数据及业务数据,用以确保数据安全。
默认角色code:admin

1.4平台管理员:属于【平台管理员角色admin】,默认用户名为admin。

1.5租户管理员角色:每个普通租户在创建时,都会指定一个租户管理员,负责租户自身的系统配置及管理。租户下的用户只能访问所属租户的数据,没有权限访问其他租户的数据,用以确保数据安全。
默认角色code:admin

1.6租户管理员:属于【租户管理员角色admin】,用户名由【平台管理员】在创建普通租户时指定。

注:【平台管理员角色】和【租户管理员角色】都是admin,区别就是【平台管理员角色】的租户ID 等于0,【租户管理员角色】的租户ID 不等于 0,有自身特有的系统菜单,这些菜单不会分派给其它角色使用。

2.多租户应用场景
2.1公有云:运营方为平台管理方,企业为租户。运营方只能创建租户,没有权限访问租户的数据,用以确保数据安全。租户的系统配置及管理只能由企业指定的【租户管理员】负责。

2.2大型企业私有云:企业部署一套私有云,由某中央单位担任平台管理方,企业的子公司为租户。因为各子公司都有自己的业务流程,所以平台管理方很难为各子公司做详细的系统配置,而且也不应该有权限访问各子公司的业务数据,同【应用场景2.1】一样,租户的系统配置及管理只能由各子公司自己指定【租户管理员】负责。

2.3中小型企业私有云:虽然依旧采用多租户,但因为企业规模较小,可以由某个部门同时担任【平台管理员】和【租户管理员】的角色,管理租户并负责各租户的系统配置。

3.单租户应用场景:系统只有一个租户。

二、方案介绍
提供统一的多租户方案满足上述的应用场景:
1.【平台管理员】只负责创建租户,为租户指定【租户管理员】账号,分派套餐。

2.在后端项目增加一个配置项,例如: bool IsAllowAddTenantAdmin = false,表示是否允许【平台管理员】向普通租户的【租户管理员】角色中添加租户管理员,默认是不允许。
IzAllowAddTenantAdmin = false时,可以满足【应用场景2.1】、【应用场景2.2】的要求。

IzAllowAddTenantAdmin = true,可以满足【应用场景2.3】的要求,此时【平台管理员】可以向租户的【租户管理员】角色中添加账户,例如:将admin账户添加到普通租户的【租户管理员】角色中;或创建几个新的账号,将【张三】添加到【租户1】、【租户2】的【租户管理员角色】中,将【李四】添加到【租户3】、【租户4】的【租户管理员角色】中,这样就可以为每个普通租户指派不同的租户管理员。

三、设计说明
为实现上述方案,基于现有的系统功能,假设所有表都已创建好但尚未添加任何配置数据时,系统操作如下。
1.使用SQL脚本初始化系统基础数据
1.1 创建默认租户/平台管理租户:
说明:在 sys_tenant 表中创建 tenant_id = 0的记录,单租户和多租户都适用。

1.2 创建【平台管理员】admin 角色,系统已实现
说明:在 sys_role 表中创建 role_code = 'admin' and tenant_id = 0 的记录

1.3 创建【平台管理员】admin 用户,系统已实现
说明: 在 sys_user 表中创建 username = 'admin' and tenant_id = 0 的记录,并加入到 admin 角色中

2.平台管理员操作
在初始化完基础数据后,就可以用admin账号登录到【平台管理租户】中,菜单:
租户管理
租户套餐(原租户默认套餐)

2.1 【租户套餐】菜单
现有功能保持不变,但需要优化【新增/编辑】页面的【菜单列表】下拉树多选框,在选中一个父节点时,自动选中所有的下阶子节点,否则菜单很多的时候,一层层展开菜单逐个选择是很繁琐的事情,影响用户体验。

2.2 【租户管理】菜单
2.2.1 修改接口 tenant/list,过滤 tenant_id = 0 的记录,避免平台管理租户显示在列表中

2.2.2 后台配置 IsAllowAddTenantAdmin = true时,【邀请用户加入】和【用户】按钮可用。
IsAllowAddTenantAdmin = false 时,【邀请用户加入】和【用户】按钮不可用,表示在【应用场景1&2】时,【平台管理员】没有权限向租户添加用户。

2.2.3 【新增租户】页面中,在“租户名称”下面新增一个文本框:【租户管理员】,保存时要修改接口 tenant/add,创建普通租户并初始化租户的数据:

a) 创建租户
说明:在 sys_tenant 表中创建 tenant_id = 租户id, admin_user = '【租户管理员】' 的记录
前提:在sys_tenant 表中新增字段 admin_user,保存租户管理员账户名,做为租户原始【租户管理员】

b) 创建【租户管理员角色】admin
说明:在 sys_role 表中创建 role_code = 'admin' and tenant_id = 租户id 的记录
前提:为 sys_role 表增加 role_code + tenant_id 唯一索引,实现:同一租户内 role_code 不重名,不同租户的 role_code 可以重名;角色编码不要由系统自动编码,保存用户填写的。

c) 创建【租户管理员】用户
说明: 在 sys_user 表中创建 username = '【租户管理员】' and tenant_id = 租户id 的账号,设置默认密码,并加入到 【租户管理员角色】admin 角色中

2.2.4 在编辑时,不允许再修改【租户管理员】的值。

2.2.5 【+套餐】按钮功能不变。

2.2.6 在工具条上新增一个【租户管理员】按钮,在IsAllowAddTenantAdmin = true 时可用,在弹出对话框中可以选择一个或多个用户,保存时将选择的用户加入到当前租户的【租户管理员角色】admin 角色中;可以通过【移除】操作按钮将用户从前租户的【租户管理员角色】admin 角色中移除,但不能移除 username = sys_tenant.admin_user 的记录,确保原始的租户管理员不被移除。

租户管理员操作
租户管理员使用【租户管理员角色】里的用户登录到租户执行系统管理等相关操作
3.1 【我的租户】菜单
3.1.1 删除【+套餐】按钮。【租户管理】菜单的【+套餐】按钮保存时,平台管理员已经为租户指定了套餐,租户管理员无权修改或重新指派套餐。

3.1.2 【用户】操作按钮的【成员】页面中,不允许移除 username = sys_tenant.admin_user 的原始租户管理员

3.2 【租户用户】菜单
此菜单取消,统一用【系统管理】下的【用户管理】菜单,

3.3 【租户角色】菜单
此菜单取消,统一用【系统管理】下的【角色管理】菜单,

其它系统功能
4.1 【用户管理】
4.1.1 主界面列表只列出 sys_user_tenant.tenant_id = 当前租户ID 的用户
4.1.2 将【租户用户】下的离职功能移植过来。

4.2 【角色管理】
4.2.1 主界面列表只列出 sys_role.tenant_id = 当前租户ID 的角色

4.2.2 【用户】操作按钮的【角色用户】界面中,只能将当前租户的用户添加到角色中。

4.2.3 【授权】操作按钮的【角色权限配置】界面中:
若当前租户ID等于 0,则列出所有的菜单
若当前租户ID不等于0,则只列出当前租户套餐内所关联的菜单。

注:因未详细看权限列表的代码逻辑,可能有其它的限制并未知晓,特此说明。

4.3 【数据字典】
系统提供的数据字典默认保存在 tenant_id 等于 0的租户内,所有的租户都可以使用这些数据字典。
但是像公司部门、职级这类数据字典,每个租户可能都有自己的定义,无法共用同一个定义,所以应允许 tenant_id 不等于 0 的租户定义同名的数据字典,来覆盖租户ID = 0的定义,所以在新建数据字典时,只要 dict_code 在同一个租户内不同名就可以。

前端登录后将当前租户以及租户ID等于0的数据字典都加载到缓存中,将查找数据字典相关的接口优化下逻辑,即可实现对默认数据字典的重定义查询:
a)查找 sys_dict.tenant_id = 当前租户ID and dict_code = ‘数据字典code’的记录,若找到则返回。
b)若 a) 点找不到,并且当前租户ID 不等于 0,则查找 sys_dict.tenant_id = 0 and dict_code = ‘数据字典code’的记录并返回结果。

完成上述修改后,任何一个租户都可以重新定义相同code的公司部门、职级或其它数据字典,以满足自身的要求。

如果想限制某些系统数据字典不被普通租户重定义,避免影响系统的正常处理逻辑,可以考虑为数据字典表增加一个字段:iz_allow_redefine,默认为 true。
这样在默认租户中,可以将界面中将一些数据字典的 iz_allow_redefine 值为 false;在普通租户中保存同名 dict_code 的时候,如果默认租户的 iz_allow_redefine 值为 false,则报错:此字典不允许重新定义。

截图&代码:

友情提示(为了提高issue处理效率):

  • 未按格式要求发帖,会被直接删掉;
  • 描述过于简单或模糊,导致无法处理的,会被直接删掉;
  • 请自己初判问题描述是否清楚,是否方便我们调查处理;
  • 针对问题请说明是Online在线功能(需说明用的主题模板),还是生成的代码功能;
@huajianpan
Copy link

写挺好,我就是新增了一个租户后,都不知道哪里去创建租户下的用户,只能去系统管理-用户管理创建,但是那又能看到其它租户的用户就很奇怪;如果用户管理进行租户隔离,那又需要一个超级管理权限的管理员租户(权限放开能看到所有租户的用户),去管理所有的普通租户(只能看到自己的租户用户)

@xiaobin620
Copy link

没有涉及到部门管理,及我的部门!

@dxiyang
Copy link

dxiyang commented May 15, 2024

看了代码,菜单权限赋值给用户两套东西,一个是sys_role_permission 角色菜单授权,一个是产品包菜单授权 sys_tenant_pack_perms

但是租户管理里有个租户角色 现在看这个租户角色好像是创建后还是得去系统管理->角色管理下操作权限 操作的权限关系数据在sys_role_permission 下

@zhangdaiscott
Copy link
Member

租户的套餐包就是权限控制

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants