Question

Je travaille sur un système rôle d'utilisateur / autorisation en PHP pour un script.

Voici un code à l'aide d'une méthode bitmask pour les autorisations que je trouve sur phpbuilder.com.

Ci-dessous cette partie est une version beaucoup plus simple w3hich pourrait faire basiquement la même chose sans la partie peu.

Beaucoup de gens ont recommandé d'utiliser les opérateurs de bits et comme pour les réglages et d'autres choses en PHP, je ne l'ai jamais compris pourquoi bien. Dans le code ci-dessous est là tout avantage d'utiliser le premier code au lieu de la seconde?

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

version non bits

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

?>
Était-ce utile?

La solution

Pourquoi ne pas faire exactement cela ...

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

Vous pouvez également créer beaucoup de combinaisons arbitraires d'autorisations si vous utilisez les 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

Autres conseils

Le premier permet aux gens d'avoir beaucoup d'autorisations - lecture / ajout / mise à jour par exemple. Le deuxième exemple, l'utilisateur vient PERMISSION_UPDATE.

test fonctionne Bitwise en testant bits pour les valeurs de vérité.

Par exemple, le 10010 de séquence binaire pourrait identifier un utilisateur avec PERMISSION_DELETE et PERMISSION_READ (le bit d'identification PERMISSION_READ est la colonne 2, le bit d'identification PERMISSION_DELETE est la colonne 16), 10010 en binaire est 18 en décimal (16 + 2 = 18). Votre deuxième exemple de code ne vous permet pas de faire ce genre de tests. Vous pouvez faire plus que les chèques-style, mais cela suppose tout le monde avec PERMISSION_DELETE devrait aussi avoir PERMISSION_UPDATE, qui ne peut être une hypothèse valable.

Peut-être juste parce que je ne me bitmasks très souvent, mais je trouve que dans une langue comme PHP où la productivité des développeurs et la lisibilité du code sont plus importants que la vitesse ou l'utilisation de la mémoire (dans certaines limites, évidemment), il n'y a pas de raison à utiliser bitmasking.

Pourquoi ne pas créer à la place une classe qui permet de suivre les choses comme les droits et les utilisateurs connectés, et ainsi de suite? Appelons-le Auth. Ensuite, si vous voulez vérifier qu'un utilisateur a une autorisation, vous pouvez créer une méthode HasPermission. par ex.,

if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
    //user can read

alors si vous voulez vérifier si elles ont une combinaison des autorisations:

if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
    //user can read, and write

ou si vous voulez vérifier si elles ont une d'un certain groupe d'autorisations:

if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
    //user can read, or write

Bien sûr, il ne peut pas être une mauvaise idée de définir des constantes, comme PERMISSION_READ, que vous pouvez simplement définir comme la chaîne « lire », et ainsi de suite.

Je trouve cette approche plus facile à lire que bitmasks parce que les noms de méthode vous dire exactement ce que vous cherchez.

Modifier : relisant la question, il semble que les autorisations de l'utilisateur reviennent de votre base de données dans un champ de bits. Si tel est le cas, vous allez devoir utiliser des opérateurs au niveau du bit. Un utilisateur qui est l'autorisation dans la base de données est 5 a PERMISSION_READ et PERMISSION_DENIED parce (PERMISSION_READ & 5) != 0 et (PERMISSION_DENIED & 5) != 0. Il ne serait pas PERMISSION_ADD, parce (PERMISSION_ADD & 5) == 0

Est-ce logique? Tous les trucs complexes dans votre exemple semble inutile bitwise.


Si vous ne comprenez pas entièrement les opérations au niveau du bit, alors ne pas les utiliser. Il ne conduira à beaucoup de maux de tête. Si vous êtes à l'aise avec eux, puis les utiliser où vous vous sentez qu'ils sont appropriés. Vous (ou celui qui a écrit le code binaire) ne semble pas saisir pleinement les opérations au niveau du bit. Il y a plusieurs problèmes avec elle, comme le fait que la fonction pow() est utilisée, qui excluaient toute sorte de prestation de performance. (Au lieu de pow(2, $n), vous devez utiliser le 1 << $n bitwise, par exemple).

Cela dit, les deux morceaux de code ne semblent pas faire les mêmes choses.

Essayez d'utiliser ce qui est dans le bit.class.php http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php

Vérification contre un bit spécifique:

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

?>

Et pour activer et désactiver:

<?php

$permissions = 8;
bit::toggle(&$permissions,PERMISSION_DENIED);

var_dump($permissions); // outputs int(9)

?>

problème de c'est si PERMISSION_READ est un masque lui-même

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

puis pour 0101 - rightWeHave $ 0011 - rightWeRequire $

il est accordé l'accès, que nous ne voulons pas probablement il devrait donc être

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

maintenant pour

0101 0011

résultat est

0001 afin que l'accès n'est pas accordée parce qu'il est pas égal à 0011

mais pour

1101 0101

il est correct que le résultat est 0101

contrôles de script qui masque a été mis en décimal. Peut-être que quelqu'un aura besoin:

<?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";

Output (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

Je suppose que le premier exemple vous donne plus de contrôle exactement les autorisations dont un utilisateur. Dans le second, vous avez juste un utilisateur « niveau »; sans doute des niveaux plus élevés héritent toutes les autorisations accordées à un utilisateur « niveau » bas, de sorte que vous n'avez pas un tel contrôle bien.

En outre, si je comprends bien, la ligne

if($user_permission_level === 4)

signifie que seuls les utilisateurs avec exactement niveau d'autorisation 4 ont accès à l'action - vous auriez sûrement vouloir vérifier que les utilisateurs ont au moins ce niveau?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top