我正在使用PHP中的用户角色/权限系统来处理脚本。
下面是我在phpbuilder.com上找到的使用位掩码方法获取权限的代码。
在那部分之下是一个更简单的版本,如果没有位部分,它可以做基本相同的事情。
许多人建议在PHP中使用位操作符等设置和其他东西,但我从未理解为什么。在下面的代码中使用第一个代码而不是第二个代码任何好处?
<?php
/**
* Correct the variables stored in array.
* @param integer $mask Integer of the bit
* @return array
*/
function bitMask($mask = 0) {
$return = array();
while ($mask > 0) {
for($i = 0, $n = 0; $i <= $mask; $i = 1 * pow(2, $n), $n++) {
$end = $i;
}
$return[] = $end;
$mask = $mask - $end;
}
sort($return);
return $return;
}
define('PERMISSION_DENIED', 0);
define('PERMISSION_READ', 1);
define('PERMISSION_ADD', 2);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 8);
//run function
// this value would be pulled from a user's setting mysql table
$_ARR_permission = bitMask('5');
if(in_array(PERMISSION_READ, $_ARR_permission)) {
echo 'Access granted.';
}else {
echo 'Access denied.';
}
?>
非位版本
<?PHP
/*
NON bitwise method
*/
// this value would be pulled from a user's setting mysql table
$user_permission_level = 4;
if($user_permission_level === 4) {
echo 'Access granted.';
}else {
echo 'Access denied.';
}
?>
答案 0 :(得分:41)
为什么不这样做......
define('PERMISSION_DENIED', 0);
define('PERMISSION_READ', 1);
define('PERMISSION_ADD', 2);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 8);
//run function
// this value would be pulled from a user's setting mysql table
$_ARR_permission = 5;
if($_ARR_permission & PERMISSION_READ) {
echo 'Access granted.';
}else {
echo 'Access denied.';
}
如果您使用位...
,您还可以创建许多任意权限组合$read_only = PERMISSION_READ;
$read_delete = PERMISSION_READ | PERMISSION_DELETE;
$full_rights = PERMISSION_DENIED | PERMISSION_READ | PERMISSION_ADD | PERMISSION_UPDATE | PERMISSION_DELETE;
//manipulating permissions is easy...
$myrights = PERMISSION_READ;
$myrights |= PERMISSION_UPDATE; // add Update permission to my rights
答案 1 :(得分:10)
第一个允许人们拥有许多权限 - 例如,读取/添加/更新。第二个例子,用户只有PERMISSION_UPDATE
。
按位测试的工作原理是测试真值的位。
例如,二进制序列10010
将标识具有PERMISSION_DELETE
和PERMISSION_READ
的用户(标识为PERMISSION_READ
的位是2的列,标识为{{的位1}}是16)的列,二进制的PERMISSION_DELETE
是十进制的18(16 + 2 = 18)。您的第二个代码示例不允许您进行此类测试。您可以执行大于样式检查,但假设10010
的所有人都应该PERMISSION_DELETE
,这可能不是一个有效的假设。
答案 2 :(得分:10)
也许这只是因为我不经常使用bitmasks,但我发现在像PHP这样的语言中,开发人员的工作效率和代码可读性比速度或内存使用更重要(显然在极限范围内),没有真正的原因使用bitmasking。
为什么不创建一个跟踪权限,登录用户等内容的类?我们称之为Auth。然后,如果要检查用户是否具有权限,则可以创建方法HasPermission。 如,
if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
//user can read
然后,如果你想检查他们是否有一些权限组合:
if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
//user can read, and write
或者如果您想检查他们是否具有任何一组权限:
if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
//user can read, or write
当然,定义常量可能不是一个坏主意,例如PERMISSION_READ,您可以将其定义为字符串'read',依此类推。
我觉得这种方法比bitmasks更容易阅读,因为方法名称可以准确地告诉你它正在寻找什么。
答案 3 :(得分:1)
编辑:重读问题,看起来用户的权限是从位域中的数据库返回的。如果是这种情况,您将不得不使用按位运算符。在数据库中5
拥有PERMISSION_READ
和PERMISSION_DENIED
的权限的用户是(PERMISSION_READ & 5) != 0
和(PERMISSION_DENIED & 5) != 0
。他不会PERMISSION_ADD
,因为(PERMISSION_ADD & 5) == 0
这有意义吗?您的按位示例中的所有复杂内容看起来都是不必要的。
如果您不完全理解按位操作,请不要使用它们。这只会导致很多麻烦。如果您对它们感到满意,那么在您认为合适的地方使用它们。您(或编写按位代码的人)似乎并不完全掌握按位操作。它有几个问题,比如使用pow()
函数的事实,它会否定任何类型的性能优势。 (例如,您应该使用按位pow(2, $n)
而不是1 << $n
。)
也就是说,这两段代码似乎没有做同样的事情。
答案 4 :(得分:1)
尝试使用http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php
中bit.class.php中的内容检查特定位:
<?php
define('PERMISSION_DENIED', 1);
define('PERMISSION_READ', 2);
define('PERMISSION_ADD', 3);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 5);
if(bit::query($permission,PERMISSION_DENIED)){
echo 'Your permission is denied';
exit();
}else{
// so on
}
?>
打开和关闭:
<?php
$permissions = 8;
bit::toggle(&$permissions,PERMISSION_DENIED);
var_dump($permissions); // outputs int(9)
?>
答案 5 :(得分:1)
问题是如果PERMISSION_READ本身就是一个掩码
if($ARR_permission & PERMISSION_READ) {
echo 'Access granted.';
}else {
echo 'Access denied.';
然后 0101 - $ rightWeHave 0011 - $ rightWeRequire
它是被授予的访问权限,我们可能不希望它应该是
if (($rightWeHave & $rightWeRequire) == $rightWeRequire) {
echo 'access granted';
}
现在是
0101 0011
结果是
0001因此不授予访问权限,因为它不等于0011
但是
1101 0101
没关系,结果是0101
答案 6 :(得分:1)
脚本检查哪个蒙版已设置为十进制。也许有人需要它:
<?php
$max = 1073741824;
$series = array(0);
$x = 1;
$input = $argv[1]; # from command line eg.'12345': php script.php 12345
$sum = 0;
# generates all bitmasks (with $max)
while ($x <= $max) {
$series[] = $x;
$x = $x * 2;
}
# show what bitmask has been set in '$argv[1]'
foreach ($series as $value) {
if ($value & $input) {
$sum += $value;
echo "$value - SET,\n";
} else {
echo "$value\n";
}
}
# sum of set masks
echo "\nSum of set masks: $sum\n\n";
输出(php maskChecker.php 123):
0
1 - SET,
2 - SET,
4
8 - SET,
16 - SET,
32 - SET,
64 - SET,
128
256
512
1024
2048
4096
8192
(...)
Sum of set mask: 123
答案 7 :(得分:0)
我想第一个例子可以让您更准确地控制用户拥有的权限。在第二个你只有一个用户'级别';可能更高的级别继承了授予较低“级别”用户的所有权限,因此您没有这样的精细控制。
另外,如果我理解正确,行
if($user_permission_level === 4)
表示只有具有完全权限级别4的用户才能访问该操作 - 当然您需要检查用户是否至少该级别?