Why should I use bitwise/bitmask in PHP?

后端 未结 8 1828
时光取名叫无心
时光取名叫无心 2020-11-30 20:54

I am working on a user-role / permission system in PHP for a script.

Below is a code using a bitmask method for permissions that I found on phpbuilder.com.

B

相关标签:
8条回答
  • 2020-11-30 21:17

    Edit: rereading the question, it looks like the user's permissions are coming back from your database in a bitfield. If that's the case, you are going to have to use bitwise operators. A user who's permission in the database is 5 has PERMISSION_READ and PERMISSION_DENIED because (PERMISSION_READ & 5) != 0, and (PERMISSION_DENIED & 5) != 0. He wouldn't have PERMISSION_ADD, because (PERMISSION_ADD & 5) == 0

    Does that make sense? All the complex stuff in your bitwise example looks unnecessary.


    If you don't fully understand bitwise operations, then don't use them. It will only lead to lots of headaches. If you are comfortable with them, then use them where you feel they are appropriate. You (or whoever wrote the bitwise code) doesn't seem to fully grasp bitwise operations. There are several problems with it, like the fact that the pow() function is used, that would negate any kind of performance benefit. (Instead of pow(2, $n), you should use the bitwise 1 << $n, for example.)

    That said, the two pieces of code do not seem to do the same things.

    0 讨论(0)
  • 2020-11-30 21:17

    Try using what is in the bit.class.php at http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php

    Checking against a specific bit:

    <?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
    }
    
    ?>
    

    And to turn on and off:

    <?php
    
    $permissions = 8;
    bit::toggle(&$permissions,PERMISSION_DENIED);
    
    var_dump($permissions); // outputs int(9)
    
    ?>
    
    0 讨论(0)
  • 2020-11-30 21:26

    Why not just do this...

    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.';
    }
    

    You can also create lots of arbitrary combinations of permissions if you use bits...

    $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
    
    0 讨论(0)
  • 2020-11-30 21:27

    I guess the first example gives you more control of exactly what permissions a user has. In the second you just have a user 'level'; presumably higher levels inherit all the permissions granted to a lower 'level' user, so you don't have such fine control.

    Also, if I have understood correctly, the line

    if($user_permission_level === 4)
    

    means that only users with exactly permission level 4 have access to the action - surely you would want to check that users have at least that level?

    0 讨论(0)
  • 2020-11-30 21:29

    problem of this is if PERMISSION_READ is a mask itself

    if($ARR_permission & PERMISSION_READ) {
        echo 'Access granted.';
    }else {
        echo 'Access denied.';
    

    then for 0101 - $rightWeHave 0011 - $rightWeRequire

    it is access granted, which we probably do not want so it should be

    if (($rightWeHave & $rightWeRequire) == $rightWeRequire) {
    echo 'access granted';
    }
    

    so now for

    0101 0011

    result is

    0001 so access is not granted because it is not equal to 0011

    but for

    1101 0101

    it is ok as the result is 0101

    0 讨论(0)
  • 2020-11-30 21:31

    The first allows people to have lots of permissions - read/add/update for example. The second example, the user has just PERMISSION_UPDATE.

    Bitwise testing works by testing bits for truth values.

    For example, the binary sequence 10010 would identify a user with PERMISSION_DELETE and PERMISSION_READ (the bit identifying PERMISSION_READ is the column for 2, the bit identifying PERMISSION_DELETE is the column for 16), 10010 in binary is 18 in decimal (16 + 2 = 18). Your second code sample doesn't allow you to do that sort of testing. You could do greater-than style checks, but that assumes everyone with PERMISSION_DELETE should also have PERMISSION_UPDATE, which may not be a valid assumption.

    0 讨论(0)
提交回复
热议问题