在PHP中实现位掩码或关系ACL [英] Implement bitmask or relational ACL in PHP

查看:92
本文介绍了在PHP中实现位掩码或关系ACL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为PHP人士熟悉E_ALLerror_reporting()函数中的其他各种位掩码常量.它们是数字常量,例如:E_ALL表示32676,而E_NOTICE表示8.我可以说我想要所有错误,但要显示通知,我可以通过将E_ALL & ~E_NOTICE作为error_reporting()的参数来实现.但实际上,我告诉它32759就是32767 - 8.

I think PHP people are familiar with the E_ALL and various other bitmask constants from the error_reporting() function. They are number constants, example: E_ALL means 32676 and E_NOTICE means 8. I can say that I want all errors but notice shown, and I do this by passing E_ALL & ~E_NOTICE as the argument of error_reporting(). But essentially, I tell it 32759 which is 32767 - 8.

这些位掩码从f(x) = 2^x函数的输出集中获取其值,并对这些值进行加法和减法,我们可以微调要得到的错误.

These bitmasks are taking their values from the output set of f(x) = 2^x function, and doing add and subtract arithmetics on these values, we can finetune what errors to get.

我正在考虑将一种可配置的访问控制项实施到我的框架中.为此,我希望设置用户的位掩码将具有相同的将数字值加在一起的方法,问题是我不知道如何实现这一点,如何根据请求的值和当前值进行检查:用户是否有权访问foobar?.

I am thinking about a more configurable access control thing to be implemented into my framework-thingy. For this, I wish to set the user's bitmask would have the same method of adding number values together, the problem is that I don't know how to pull this off, how to check against the requested and the present value: Does the user have rights to access foobar?.

另一个问题是可伸缩性.我可能只有31个唯一的位(由于2^32到达太大且无法维护的状态),如果我需要经历(目前尚未真正计划)此障碍,将很难迁移?我对访问控制的另一种想法是建立一个表,将user.id和他具有的访问位的整数值链接在一起.

And the other problem is scalability. I might only have 31 unique bits (as 2^32 reaches the too big and unmaintainable state), and it would be hard to migrate if I need to undergo (not really planned right now) this barrier? My other thought for access control would be setting up a table which links together the user.id and the integer value of the access bit he has.

总结一下,以下两个选项中的哪一个是更好的解决方案?:

  • 使用用户表中的一个字段存储位掩码,然后在需要时从中获取请求的位.
  • 在表中定义了一组访问标志,并具有一个关系表,该表将用户链接到访问,从而利用关系数据库的精妙之处满足我们的需求.

我正在研究第二种方法,但是我不知道哪种方法最适合使用.

I was researching about the second method, but I don't know which one would be the best to use.

推荐答案

位掩码

位掩码的原始问题是它们违反了数据建模的惯例(在此处的另一个答案中表示,进一步阅读此处

Bitmasks

The original problem with bitmasks is that they go against the conventions of data modelling (expressed in another answer here, with further reading here and here). A 4-byte signed integer might only contain 31 different values (represented in integer as 2 147 483 648) and calculation is hard with them. There have been various questions on Stack Overflow before discussing this topic, which I used to get a sense of implementation of how bistmasks would work.

测试还显示,使用位掩码非常困难.需要了解按位运算符,并且迁移基本上变得不可能. (不可能的意思是,起初,实现位掩码似乎是

Testing also revealed that working with bitmasks is hard. It needs a sense to understand the bitwise operators, and migration becomes basically impossible. (By impossible I mean that, at first, implementing bitmasks seemed a good thing to do, but after all it turned out it requires too much expends compared to the benefit it could give in return.) Take a basic portal-like website... I mean no. Take Stack Overflow as an example, and how much unique privileges it has. I have actually tried to make a count but lost myself in complexity, but the amount we would need is way close, if not already over the said barrier of 31 unique values. There is a very likely chance that an update on the project which alters bitmask meanings result in a long need of recalculation, and it is a lot more error prone if confronted by database errors.

虽然我没有确切,准确的时序图,但是使用位掩码比ACL慢.比较数据库大小,内存和存储空间会更大,而我们利用关系数据库和索引功能的机会就更少.对于网站上的用户权限,如果我们可以使用其他方法,则位掩码是禁止.

While I don't have the exact, pinpoint timing figures, using bitmasks felt slower than ACL. Comparing database sizes, memory and storage footprint is bigger and we have less chance to exploit the relational database and indexing capabilities. For user permissions on a website, bitmasks are a no-go, if we have other methods we might use.

在各种系统中,位掩码可以起作用,即 MaNGOS (我从中最初提出了这个想法),其中item_template和其他各种 template 表定义了使用位掩码的 flags .但最重要的是,在这些表中,这些值不太可能改变,其计算结果为只读,这与用户随意获得和失去特权的网站相反.

There are various systems where bitmasks do works, namely MaNGOS (from which I originally came up with the idea), where item_template and various other template tables define flags which makes use of bitmasks. But the bottom line is that in these tables, the values are unlikely to ever change, the calculation is read-only, contrary to websites where users arbitrarily obtain and lose privileges.

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)

Etcetera.

由于各种 问题恰当地描述了该方法,而我将永远无法描述它.位掩码看起来不错,位掩码看起来很奇特,但是让它们在生产中安顿下来是没有意义的.

I will spare you the lines of code because various other questions describe the method aptly, in a way I will never be able to describe it. Bitmasks seem to be nice, bitmasks seem to be exotic, but there is no point letting them settle in production.

原始问题中描述的另一个选项是利用关系数据库和SQL语言来设置数据库中的权限.我们将需要在数据库中再创建两个表:

The other option which was described in the original question was to exploit the relational database and the SQL language to set up the permissions in the database. We will need to create two more tables into our database:

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的关系.之后,这只是我们如何组合编程逻辑的问题.

perm_relation.perm_id will be the foreign key pointing to permission.id, and perm_relation.user_id will be our relation to users.id. After this, it's only a matter of how we put together our programming logic.

SELECT row_id FROM perm_relation
WHERE perm_id = (SELECT id FROM permission WHERE name = "U_SUPERADMIN")
AND user_id = CURRENT_USER_ID;

使用此方法,我们可以实现更大的兼容性,更快的执行和更轻松的迁移.只需定义新权限并将新权限分配给任意用户,便只需花费一小段时间即可添加新权限.删除同样容易,它只需要一个小的SQL查询就可以优化我们的表以删除孤立的整体(例如:具有系统权限但没有在系统中定义相关权限的用户).

Using this method we bind towards greater compatibility, quicker execution and easier migration. It takes only a neck of time to add new permissions, both as defining new ones and grating some to arbitrary users. Deletion is just as easy and it takes only a small SQL query to optimize our tables to remove orphan entires (for example: users having permissions given to them without related permission defined in the system).

因为我们要在PHP环境中实现该系统,所以我们可以假定将有某种依赖于此权限列表的管理页面,其中许多功能都取决于此权限列表.列出通过其拥有的权限过滤的用户的示例就是一个示例.在这种情况下,ACL比位掩码要好得多,因为我们可以进一步利用JOIN语句...甚至更多.

Because we are implementing this system into a PHP environment, we can assume that there will be some sort of administrative page with many features relying on this permission list. An example of listing users filtered by the permission they have would be one example. In this context, ACL is a lot better than bitmasks, because we can take further exploits of JOIN statements... and even beyond.

结论是,位掩码和关系模式具有不同的用途.对于用户权限系统,位掩码太多且非常庞大,而关系表在上面提到的MaNGOS示例中会显得过大.

The conclusion is that bitmasks and the relational pattern has different purposes. Bitmasks are too much and very bulk for a user permission system, while relational tables would be an overkill in the MaNGOS example mentioned above.

这篇关于在PHP中实现位掩码或关系ACL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆