权限:按位操作或多对多子表?

时间:2013-03-21 21:25:40

标签: php mysql permissions bit-manipulation

我正在尝试了解使用权限的最佳方式,据我所知,有两个主要选项。

第一个选项是使用按位运算,为此我将使用以下数据库结构:

用户

user_id | user_permission
---------------------
1       | 15
2       | 1

权限

permission_id | permission_name
-----------------------
1             | Read
2             | Write
4             | Execute
8             | Delete

然后检查用户是否有权限我将使用该操作:

$user_permission & $permission_id

我看到的主要好处是:

  1. 设置,获取和验证权限的琐碎
  2. 减少存储空间(没有子数据库;每个用户权限没有其他行)
  3. 我看到的主要缺点是:

    1. 列出用户权限稍微复杂一些
    2. 无法使用外键约束
    3. 有限权限(如果使用BIGINT则为64)
    4. 第二个选项是使用多对多子表,为此我将使用以下数据库结构:

      用户

      user_id
      -------
      1      
      2      
      

      权限

      permission_id | permission_name
      -----------------------
      1             | Read
      2             | Write
      3             | Execute
      4             | Delete
      

      user_permissions

      user_id | permission_id
      -----------------------
      1       | 1
      1       | 2
      1       | 3
      1       | 4
      2       | 1
      

      然后检查用户是否有权限我会使用该操作(其中$user_permissionpermission_id的数组):

      in_array($permission_id, $user_permission);
      

      我看到的主要好处是:

      1. 可以使用外键约束
      2. 无法列出用户的权限
      3. 允许更多的权限
      4. 我看到的主要缺点是:

        1. 更大的存储空间(子数据库;每个用户权限的额外行数)
        2. 设置和获取权限稍微复杂
        3. 问题

          哪个是更好的选择?我看到每个的好处和缺点,不确定哪个更合适。虽然我知道背景可能起作用;那么在哪种情况下,按位操作会更好,而且多对多子表会更好?还是有第三种选择,我不知道?

          我目前更倾向于使用多对多表来获得外键约束的好处以及更多的权限可能性,但我想知道我是否遗漏了其他内容;按位操作权限似乎非常普遍,所以我认为有充分的理由使用它们。

2 个答案:

答案 0 :(得分:6)

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

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

表1 :用于存储权限名称的权限表,如1,2,4,8..etc(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'拥有'User-Add'(位= 1)和'Blog-Delete'(位64)的权限,那么角色将为65(1 + 64)。
如果用户'Mehata'拥有'Blog-View'(位= 128)和'User-Delete'(位-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://goo.gl/ATnj6j

答案 1 :(得分:2)

我不会选择按位操作解决方案。除非你真的非常狭隘的空间,否则将其分解为自己的表和映射表不会花费那么多磁盘。对于不是您的人来说,理解起来会更容易,并且您可以通过这种方式更轻松地实施FK关系。此外,正如您所提到的,权限数量可以无限制地增长。根据您对表的索引方式,像“向我显示具有读取权限的所有用户”这样的查询似乎更快更容易理解(这是主观的,我意识到)。