php - 权限:按位运算还是多对多子表?

标签 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. 更少的存储(没有子数据库;每个用户权限没有额外的行)

我看到的主要缺点是:

  1. 列出用户的权限稍微复杂一些
  2. 不能使用外键约束
  3. 有限权限(如果使用 BIGINT,则为 64)

第二种选择是使用多对多子表,为此我会使用以下数据库结构:

用户

user_id
-------
1      
2      

权限

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

用户权限

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

然后为了检查用户是否具有权限,我将使用操作(其中 $user_permission 是一个 permission_id 数组):

in_array($permission_id, $user_permission);

我看到的主要好处是:

  1. 可以使用外键约束
  2. 列出用户的权限很简单
  3. 允许更多的权限

我看到的主要缺点是:

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

问题

以下哪一个是更好的选择?我看到了每种方法的优点和缺点,不确定哪种更合适。尽管我知道上下文可能起作用;那么在哪些情况下按位操作会更好,在哪些情况下多对多子表会更好?还是有我不知道的第三种选择?

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

最佳答案

我认为按位运算符是实现用户权限的最佳方式。 在这里,我将展示如何使用 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' (bit=1) 和 'Blog-Delete' (bit-64) 权限,则角色将为 65 (1+64)。
如果用户“Mehata”具有“Blog-View”(bit=128)和“User-Delete”(bit-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

关于php - 权限:按位运算还是多对多子表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15558460/

相关文章:

mysql - 您可以将 CHAR 设置为 NULL 或空字符串吗?

MySQL触发器: Check if primary key ID is in use in other table

android - 我必须向 list 添加哪个权限才能获取 gps 传感器读数?

php - 如何在 Codeigniter 中将事件 session ID 解析为外键

PHP 使用 FetchAll 创建函数

php - 表 MYSQL 中的重复项

javascript - 在新选项卡中打开页面时,JSON 或 AJAX 请求未显示在控制台中

python - Django 设置.py 错误

user-interface - 如何避免滥用用户界面的角色和权限?

用户 'NT AUTHORITY\NETWORK SERVICE' 的 ASP.NET 登录失败