多租户系统 - 隐藏租户管理权限

优质
小牛编辑
135浏览
2023-12-01

我们现在有点问题:因为用户 tenant2Administration:Security 权限,所以他可以访问用户和角色权限对话框。因此,他可以使用权限 UI 给自己授予 Administration:Tenants 权限。

Tenant2 Granting Himself

Serenity 扫描程序集的特性,比如 ReadPermissionWritePermissionPageAuthorizeServiceAuthorize 等,并在编辑权限对话框列出这些权限。

我们应该先从默认值列表中删除它。

在 UserPermissionRepository.cs 找到 ListPermissionKeys 方法:

  1. public ListResponse<string> ListPermissionKeys()
  2. {
  3. return LocalCache.Get("Administration:PermissionKeys", TimeSpan.Zero, () =>
  4. {
  5. //...
  6. result.Remove(Administration.PermissionKeys.Tenants);
  7. result.Remove("*");
  8. result.Remove("?");
  9. //...

现在,该权限不会在 编辑用户权限编辑角色权限 对话框中被列出来。

但是,黑客仍然可以通过 UserPermissionRepository.UpdateRolePermissionRepository.Update 方法给自己授权。

我们应该添加一些检查来阻止该行为:

  1. public class UserPermissionRepository
  2. {
  3. public SaveResponse Update(IUnitOfWork uow,
  4. UserPermissionUpdateRequest request)
  5. {
  6. //...
  7. var newList = new Dictionary<string, bool>(
  8. StringComparer.OrdinalIgnoreCase);
  9. foreach (var p in request.Permissions)
  10. newList[p.PermissionKey] = p.Grant ?? false;
  11. var allowedKeys = ListPermissionKeys()
  12. .Entities.ToDictionary(x => x);
  13. if (newList.Keys.Any(x => !allowedKeys.ContainsKey(x)))
  14. throw new AccessViolationException();
  15. //...
  1. public class RolePermissionRepository
  2. {
  3. public SaveResponse Update(IUnitOfWork uow,
  4. RolePermissionUpdateRequest request)
  5. {
  6. //...
  7. var newList = new HashSet<string>(
  8. request.Permissions.ToList(),
  9. StringComparer.OrdinalIgnoreCase);
  10. var allowedKeys = new UserPermissionRepository()
  11. .ListPermissionKeys()
  12. .Entities.ToDictionary(x => x);
  13. if (newList.Any(x => !allowedKeys.ContainsKey(x)))
  14. throw new AccessViolationException();
  15. //...

在这里,我们认为任何试图授权不在权限对话框列表的新访问许可键都是一个黑客行为。

实际上,即使在非多租户系统中也应该默认做这个检查,但是通常我们信任管理的用户。在这里,管理员只能管理他们自己的租户,所以我们必须包含该检查。