设计用户角色和权限系统的最佳实践?

时间:2008-12-02 10:56:04

标签: mysql database database-design

我需要将用户角色和权限系统添加到使用PHP / MySQL构建的Web应用程序中。我希望有这个功能:

  1. 一个root用户可以创建子根,组,规则和普通用户(所有权限)。
  2. 子根只能为他/她自己的组(没有组)创建规则,权限和用户。
  3. 用户可以根据分配给他的权限,按组root访问由他或他的团队创建的内容。
  4. 我需要系统足够灵活,以便为内容分配新的角色和权限。

    我有一个users表存储组密钥以及其他信息。目前,我在每个内容表中使用两个字段,即createdByCreatedByGroup,并将其用作某个用户是否具有权限的点。但它不够灵活,因为对于每一个新内容,我都必须通过所有数据更新和权限更新。请通过讨论架构设计的最佳实践来帮助我。

5 个答案:

答案 0 :(得分:34)

适合您需求的模式称为role-based access control

PHP中有几个很好的实现,包括Zend_Acl(良好的文档),phpGACLTinyACL。大多数框架也以某种形式拥有自己的ACL实现。

即使你选择自己动手,它也会帮助你检查那些很好的解决方案。

答案 1 :(得分:34)

我认为按位运算符是实现用户权限的最佳方式。 在这里,我将展示如何使用MySQL实现它。

以下是包含一些示例数据的示例表:

表1 :用于存储权限名称的权限表,如1,2,4,8 ..等等(2的倍数)

CREATE TABLE IF NOT EXISTS `permission` (
  `bit` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`bit`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

将一些样本数据插入表中。

INSERT INTO `permission` (`bit`, `name`) VALUES
(1, 'User-Add'),
(2, 'User-Edit'),
(4, 'User-Delete'),
(8, 'User-View'),
(16, 'Blog-Add'),
(32, 'Blog-Edit'),
(64, 'Blog-Delete'),
(128, 'Blog-View');

表2 :用于存储用户ID,名称和角色的用户表。角色将计算为权限总和 示例:

如果用户' Ketan'获得用户添加'的许可(位= 1)和'博客 - 删除' (bit-64)所以角色是65(1 + 64) 如果用户' Mehata'获得“博客查看”的许可。 (位= 128)和'用户删除' (第4位)所以角色将是132(128 + 4)。

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `role` int(11) NOT NULL,
  `created_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

示例数据 -

INSERT INTO `user` (`id`, `name`, `role`, `created_date`)
   VALUES (NULL, 'Ketan', '65', '2013-01-09 00:00:00'),
   (NULL, 'Mehata', '132', '2013-01-09 00:00:00');

获得用户的许可 登录后如果我们要加载用户权限,那么我们可以在下面查询以获取权限:

SELECT permission.bit,permission.name  
   FROM user LEFT JOIN permission ON user.role & permission.bit
 WHERE user.id = 1

这里是user.role"&" permission.bit是一个按位运算符,它将输出为 -

User-Add - 1
Blog-Delete - 64

如果我们想要检查特定用户是否具有用户编辑权限 -

  SELECT * FROM `user` 
     WHERE role & (select bit from permission where name='user-edit')

输出=无行。

您还可以看到:http://sforsuresh.in/implemention-of-user-permission-with-php-mysql-bitwise-operators/

答案 2 :(得分:6)

我的结构略有不同,但它应该可以作为参考。

每个用户都有一个'Role','GroupID'与之关联,以及GroupID引用的Group表。 然后我有3个权限表。

PermissionMaster(FormName)

PermissionChild(PermissionMasterID, PermissionName, Desc, DefaultValue, DependOn)

PermissionGroupChild(GroupID, PermissionChildID, Allow)

PermissionMaster包含权限引用的名称/表单/模块。 PermissionChild将列出每个主人可用的所有可能权限,例如“创建”,“查看”,“编辑”,“删除”和描述(我在第一个版本上没有这个,并且它开始变得混乱即使对于1个模块,也有太多的权限设置)。我允许添加更多的孩子来专门引用某些功能,比如'ChangeTimeStamp',这也允许更多特定权限,然后'编辑'

然后PermissionGroupChild是PermissionChild和Group表之间的链接。每个组都将复制一组PermissionChild并使用默认设置进行设置。然后我有一个权限类,它执行表查询并检查每个用户。我只在登录时加载它。然后在每个表单/模块中,我检查它是否具有适当的权限并正确应用UI。

至于角色,我只在登录配置页面使用它。较小的角色值意味着更高的排名。因此,用户只能看到自己和角色值高于自身的用户。他/她可以编辑低于自身但不相似的那些。

答案 3 :(得分:6)

您可能不需要权限组。而是创建用户组,授予用户组权限,并将用户放入组中。用户还应该能够覆盖他们所在组的权限。拒绝应该总是覆盖授权,其中用户在多个具有权限的组中。

总结:

  • 用户拥有零个或多个权限(grany,deny)
  • 用户属于零个或多个群组
  • 群组拥有零个或多个权限(grant,deny)

答案 4 :(得分:2)

我有群组和用户(如活动目录LDAP解决方案)。因此,如果我提供对组I的访问权限,则需要该组中的用户具有访问权限。

所以,根据下面的@suresh-kamrushi答案,我做了这个:

INSERT INTO `permission` (`bit`, `name`) VALUES
(1,   'add-yes'),
(2,   'add-no'),
(4,   'edit-yes'),
(8,   'edit-no'),
(16,  'del-yes'),
(32,  'del-no'),
(64,  'view-yes'),
(128, 'view-no');

如果用户有位00000000,我会先取两个数字00,这意味着add-yesadd-no将从群组权限中删除。

如果用户有位01010110,我会先取两个数字01,这意味着add-no会对群组权限进行素数处理,因此该用户没有添加权限。这按位表示用户只能查看。

它还与家长小组合作。

您对此解决方案有何看法? 有没有人有更好的方法呢?