位掩码
位掩码的原始问题是它们违反了数据建模的约定(在此处的另一个答案中表达,在此处和此处进一步阅读)。一个 4 字节的有符号整数可能只包含31
不同的值(用整数表示为2 147 483 648
),并且很难用它们进行计算。在讨论这个话题之前,Stack Overflow 上有各种各样的问题,我曾经通过这些问题来了解 bistmasks 的工作原理。
测试还表明使用位掩码很难。理解位运算符需要一种感觉,并且迁移基本上是不可能的。(不可能我的意思是,起初,实施位掩码似乎是一件好事,但毕竟与它可以带来的好处相比,它需要太多的支出。)以一个基本的类似门户的网站.. . 我的意思是没有。以堆栈溢出为例例如,它有多少独特的特权。实际上,我曾尝试进行计数,但在复杂性中迷失了自己,但我们需要的数量非常接近,如果还没有超过 31 个唯一值的上述障碍的话。更改位掩码含义的项目更新很可能导致长期需要重新计算,并且如果遇到数据库错误,则更容易出错。
虽然我没有准确的、精确的时序数据,但使用位掩码感觉比 ACL 慢。比较数据库大小,内存和存储空间更大,我们利用关系数据库和索引功能的机会更少。对于网站上的用户权限,如果我们有其他可能使用的方法,位掩码是不行的。
位掩码可以在多种系统中发挥作用,即MaNGOS (我最初是从这里提出这个想法的),其中和其他各种模板表定义了使用位掩码的标志。但最重要的是,在这些表中,值不可能永远改变,计算是只读的,与用户任意获得和失去权限的网站相反。item_template
示例代码
define('U_NIL', 0);
define('U_EXEC', 1);
define('U_WRIT', 2);
define('U_READ', 4);
$our_perm = 7;
$req_perm = U_EXEC | U_WRIT | U_READ;
var_dump( ($our_perm & $req_perm) == $req_perm ); # Will be bool(true)
$our_perm = 3;
var_dump( ... The same thing ...); # Will be bool(false)
$our_perm = U_READ;
$req_perm = U_READ | U_WRIT;
var_dumo(...); # Will be bool(false)
$our_perm = U_READ | U_WRIT | U_EXEC;
$req_perm = U_READ;
var_dump(...); # Will be bool(true)
等等。
我将省去你的代码行,因为各种 其他 问题恰当地描述了该方法,在某种程度上我永远无法描述它。位掩码看起来不错,位掩码似乎很奇特,但让它们在生产中安定下来是没有意义的。
访问控制列表
原始问题中描述的另一个选项是利用关系数据库和 SQL 语言在数据库中设置权限。我们需要在数据库中再创建两个表:
CREATE TABLE `perm_relation` (
`row_id` int(10) NOT NULL AUTO_INCREMENT,
`user_id` int(10) NOT NULL,
`perm_id` int(10) NOT NULL,
PRIMARY KEY (`row_id`),
UNIQUE `permission` (`user_id`, `perm_id`)
) ENGINE=InnoDB;
CREATE TABLE `permission` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
PRIMARY KEY (`row_id`)
) ENGINE=InnoDB;
perm_relation.perm_id
将是指向的外键permission.id
,perm_relation.user_id
将是我们的关系users.id
。在此之后,这只是我们如何组合我们的编程逻辑的问题。
SELECT row_id FROM perm_relation
WHERE perm_id = (SELECT id FROM permission WHERE name = "U_SUPERADMIN")
AND user_id = CURRENT_USER_ID;
使用这种方法,我们可以实现更高的兼容性、更快的执行和更轻松的迁移。添加新权限只需要很短的时间,既可以定义新权限,也可以将一些权限授予任意用户。删除同样简单,只需要一个小的 SQL 查询来优化我们的表以删除孤立的整体(例如:具有权限的用户没有在系统中定义相关权限)。
因为我们将这个系统实现到 PHP 环境中,我们可以假设会有某种管理页面,其中有许多依赖于这个权限列表的特性。列出按他们拥有的权限过滤的用户的示例就是一个示例。在这种情况下,ACL 比位掩码好得多,因为我们可以进一步利用JOIN
语句……甚至更多。
结论是位掩码和关系模式有不同的用途。位掩码对于用户权限系统来说太多且非常庞大,而在上面提到的 MaNGOS 示例中,关系表将是一种过度杀伤力。