【问题标题】:Managing user permissions with a hierarchy使用层次结构管理用户权限
【发布时间】:2011-11-21 07:52:09
【问题描述】:

我正在构建一个系统,组织将在其中输入与其业务相关的信息。报告需要向多个级别的用户提供,其中一些用户只能访问其组织的统计数据,而更高级别的用户将可以访问单个组织的统计数据以及更高级别实体的汇总统计数据(请参阅我的图表,其中说明了层次结构)。

  • 市内将有一个或多个组织。
  • 一个县将有一个或多个直辖市
  • 一个州会有一个或多个县
  • 会有一个或多个状态
  • 可以随时添加组织、市、县和州
  • 将组织、市、县添加到系统时,已经有权查看该州的用户应该能够自动查看新组织/市/县的报告,而无需管理员明确授予他们权限.这同样适用于有权查看市级和县级报告的用户,只要将层次结构中低于他们的新实体添加到系统中。

一些例子:

用户 1:只能查看组织 #1 的报告

用户 2:可以查看市政当局 #2 下所有组织的报告

用户 3:可以查看市政当局 #1 和 #2 下所有组织的报告

用户 4:可以查看县 #3 下所有组织的报告

用户 5:可以查看州 #3 下所有县的报告

我的问题是如何组织这个?我不确定在不向各个组织分配权限的情况下为报告分配权限的最佳方式。这显然是不切实际的。

我在这里看到了一些与 ACL 相关的问题,但它们似乎并不适用于此。如果是这样,那么解释它与 ACL 的关系也将是一个令人满意的答案。

【问题讨论】:

    标签: php mysql reporting user-permissions


    【解决方案1】:

    我认为一种方法是为每个实体(组织、市、县、州)分配一个唯一的权限 ID

    因此,您的表应该有一个新列 permission_id,格式如下: 组织 1 将具有 permission_id O1 组织 2 将拥有权限 ID O2

    Municipality 1 将拥有权限 ID M1 自治市 2 将拥有权限 ID M2

    等等。

    然后,你可以制作一个权限表(id、id_user、permissions) 权限列将类似于 O1 - 仅允许 Organisation1 M1 - 1 市所有组织的许可 M1M2 - 市政 1 和 2 中所有组织的许可

    S1 - 状态 1 的权限

    这只是我的看法。只要您知道用户可以访问某个自治市,他就应该可以访问该自治市下的所有内容。 一些可以从当前实体获取路由的php函数可以匹配用户权限。

    例子。

    您在市政页面上。 M2。拥有 S2 权限的用户 您的函数将获得城市 ID 作为参数,并且该函数将创建一条路线: M2 、 C3 、 S1 。然后将 S2 与 S1 进行比较,并且权限被拒绝。这样,复杂度为 O(n),其中 n 是实体的数量(组织、市、县和州,即 4)。

    【讨论】:

      【解决方案2】:

      我建议在您的数据库中创建一系列用户组,每个用户组中都有一个或多个用户帐户级别,然后将整数作为分层值分配给组,然后对各个帐户级别执行相同操作在组内,类似这样(这是一个关系结构,使用 InnoDB):

      table: account_groups (Broader account groupings)
      Fields:
      -id_key - primary key, auto number
      -group - unique index
      -parent - index, foreign key=account_groups.group (this allows you to create group trees, so you can specify that a county group belongs to a state, and a municipality belongs to a county group, etc.)
      -group_hierarchy - integer (0 is highest permission group, each subsequent one step lower)
      
      table: account_levels (Account levels within a group)
      Fields:
      -id_key - primary key, auto number
      -account_level - unique index
      -group - index, foreign key=account_groups.group
      -account_heirarchy - integer (same as other table but denotes heirarchy within the group
      
      table: user_accounts (Individual user accounts)
      Fields:
      -id_key - primary key, auto number
      -account_id - unique index, user account name
      -account_level - index, foreign key=account_levels.account_level
      
      table: user_groups (denotes which tree(s) the user has access to)
      Fields:
      -id_key - primary key, auto number
      -account_id - index, foreign key=user_accounts.account_id
      -group - index, foreign key=account_groups.group
      

      然后是权限:

      table: permissions (directory of permissions that could be applied)
      Fields:
      -id_key - primary key, auto number
      -permission - unique index, permission identifier
      -other stuff you need associated with the individual permissions, based on how you want them to hook into your program
      
      table: permissions_group_permissions (permissions applied at group level)
      Fields:
      -id_key - primary key, auto number
      -group - index, foreign key=account_groups.group
      -permission - index, foreign key= permissions.permission
      
      table: permissions_account_permissions (permissions applied at account level)
      Fields:
      -id_key - primary key, auto number
      -account_type - index, foreign key=account_levels.account_level
      -permission - index, foreign key=permissions.permission
      
      table: permissions_individual_permissions (permissions applied to individual accounts, if neccessary)
      Fields:
      -id_key - primary key, auto number
      -account_id - index, foreign key=user_accounts.account_id
      -permission - index, foreign key=permissions.permission
      -allow_or_deny - boolean (TRUE means permission is granted, FALSE means permission if revoked. This allows you to fine tune individual accounts, either granting custom elevated permissions, or revoking individual permissions for troublesome accounts without demoting them from the group. This can be useful in some special circumstances)
      -expiration - timestamp (allows you to set expiration dates for permissions, like if you want to temporarily suspend a specific action. Programmatically set default value of 00/00/00 00:00:00 as indefinite. You can do this at the account and group levels too by adding this field to those tables.)
      

      然后您可以使用 php 来迭代单个帐户的权限,方法是首先获取与帐户级别关联的组,按层次顺序制作每个后续组的数组,然后迭代当前的层次顺序组(作为多维数组添加到组数组)从组内的当前帐户级别到组内的最后一个现有帐户级别。接下来,您将获取每个后续​​组的所有帐户级别,最后获取已添加到数组中的每个帐户级别的所有关联权限。如果您实现单个用户权限,则需要在您的权限数组中附加单独应用的权限,最后从您的数组中删除其 allow_or_deny 字段设置为 FALSE 的所有权限。如果用户需要访问多个树,您可以在 account_groups 表中添加一条与他们的帐户 ID 匹配的记录,表示他们有权访问的树的最高级别是什么,然后遍历树中的所有后续组。要向帐户授予所有适用权限,请从 user_groups 中获取 account_id 的所有组关联,然后为每个树运行前面描述的过程。如果他们只能访问一棵树,您甚至不需要使用 user_groups 表。

      an example of how the structure fits your model:
      group: USA, hierarchy = 0
      group: California, parent-> USA, hierarchy = 1
      group: Los Angeles, parent->California, hierarchy = 2
      group: Texas, parent->USA, hierarchy = 1
      group: Dallas, parent->Texas, hierarchy = 2
      

      美国组的成员可以访问所有内容。加利福尼亚州的成员可以访问加利福尼亚州层次结构中的所有后续组,但不能访问德克萨斯州的组,即使它们具有相同的层次值(因为它们是不同的父分支)

      account levels:
      admin, hierarchy=0
      manager, hierarchy=1
      analyst, hierarchy=2
      staff member, hierarchy=3
      

      每个帐户级别都具有每个后续帐户级别的所有权限。

      user accounts:
      Bob, manager (likes to spam junk email to everyone)
      

      您仍然可以通过将电子邮件权限添加到 permissions_individual_permissions 并将 allow_or_deny 值设置为 FALSE 来撤销 Bob 的电子邮件权限。这可以让您阻止 Bob 发送垃圾邮件,而不会将他从管理层降级。

      example PHP array:
      $account=array(
          groups=>array(), //Step 1: array_push each group the account is a member of here. Repeat for each tree from user_groups.
          account_levels=>array(), //Step 2: loop through $account[groups], array_push each level here
          permissions=>array(), //Step 3: loop through $account[account_levels], array_push each permission here. Then do the same for individual permissions applied to the account
          restrictions=>array() //Step 4: loop through individual permissions where allow_or_deny=FALSE, array_push here (do the same for group and account level if you implemented restrictions for those tables as well). Tell your program to ignore permissions from this array, even if the account would otherwise have them.
      );
      

      【讨论】:

      • 另外,这将允许您为不同的树设置不同的权限级别,因此单个用户可以在一棵树中拥有状态访问权限,但在另一棵树中只有市政访问权限。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 2022-11-04
      • 2016-03-27
      • 1970-01-01
      • 2022-12-21
      • 2023-01-09
      相关资源
      最近更新 更多