Domanda

Sto lavorando su un sistema user-ruolo / l'autorizzazione in PHP per uno script.

Di seguito è un codice utilizza un metodo maschera di bit per i permessi che ho trovato sul phpbuilder.com.

Di seguito quella parte è una versione molto più semplice w3hich poteva fare fondamentalmente la stessa cosa senza la parte bit.

Molte persone hanno raccomandato di utilizzare gli operatori bit e come per le impostazioni e altre cose in PHP, non ho mai capito perché però. Nel codice qui sotto c'è alcun beneficio di utilizzare il primo codice al posto della seconda?

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

versione non-bit

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

?>
È stato utile?

Soluzione

Perché non fare questo ...

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

È inoltre possibile creare un sacco di combinazioni arbitrarie di permessi, se si utilizza bit ...

$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

Altri suggerimenti

Il primo permette alle persone di avere un sacco di permessi - leggi / aggiungere / aggiornamento per esempio. Il secondo esempio, l'utente ha appena PERMISSION_UPDATE.

bit a bit test funziona analizzando i bit per i valori di verità.

Ad esempio, la sequenza 10010 binaria potrebbe identificare un utente con PERMISSION_DELETE e PERMISSION_READ (il bit che identifica PERMISSION_READ è la colonna per 2, il bit che identifica PERMISSION_DELETE è la colonna per 16), 10010 in binario è 18 in decimale (16 + 2 = 18). Il tuo secondo esempio di codice non consente di fare questo tipo di test. Si potrebbe fare maggiore di controlli di stile, ma che assume tutti con PERMISSION_DELETE dovrebbe avere anche PERMISSION_UPDATE, che non può essere un presupposto valido.

Forse è solo perché io non uso bitmasks molto spesso, ma trovo che in un linguaggio come PHP, dove la produttività degli sviluppatori e la leggibilità del codice sono più importante della velocità o l'utilizzo della memoria (entro certi limiti, ovviamente), non c'è alcun motivo reale utilizzare bitmasking.

Perché non invece creare una classe che tiene traccia di cose come i permessi, e loggati, e così via? Chiamiamola Auth. Poi, se si desidera controllare che un utente ha un permesso, è possibile creare un metodo di hasPermission. per es.,

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

Poi, se si desidera controllare se hanno una qualche combinazione di permesso:

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

o se si desidera controllare se hanno qualsiasi di un certo gruppo di permesso:

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

Naturalmente, potrebbe non essere una cattiva idea per definire le costanti, come PERMISSION_READ, che si può solo definire come la stringa 'leggere', e così via.

Trovo che questo approccio più facile da leggere rispetto bitmasks perché i nomi dei metodi ti dicono esattamente che cosa è che stai cercando.

Modifica : rileggendo la questione, sembra che le autorizzazioni dell'utente stanno tornando dal database in un campo di bit. Se questo è il caso, si sta andando ad avere per utilizzare gli operatori bit a bit. Un utente che è permesso nel database è 5 ha PERMISSION_READ e PERMISSION_DENIED perché (PERMISSION_READ & 5) != 0 e (PERMISSION_DENIED & 5) != 0. Non avrebbe PERMISSION_ADD, perché (PERMISSION_ADD & 5) == 0

Ha senso? Tutta la roba complessa nel tuo esempio bit a bit sembra superfluo.


Se non comprendere appieno operazioni bit per bit, quindi non li usano. 'solo portare a un sacco di mal di testa. Se hai dimestichezza con loro, poi usarli in cui ti senti siano appropriate. È (o chi ha scritto il codice bit a bit) non sembra cogliere appieno operazioni bit per bit. Ci sono diversi problemi con esso, come il fatto che la funzione pow() viene utilizzato, che sarebbe negare qualsiasi tipo di miglioramento delle prestazioni. (Invece di pow(2, $n), è necessario utilizzare il 1 << $n bit per bit, per esempio.)

Detto questo, i due pezzi di codice non sembrano fare le stesse cose.

Prova a usare ciò che è nel bit.class.php all'indirizzo http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php

Controllato contro un po 'particolare:

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

?>

E per accendere e spegnere:

<?php

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

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

?>

problema di questo è che se PERMISSION_READ è una maschera stessa

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

poi per 0101 - $ rightWeHave 0011 - $ rightWeRequire

è l'accesso concesso, che probabilmente non vogliamo quindi dovrebbe essere

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

così ora

0101 0011

risultato è

0001 quindi l'accesso non è concesso perché non è uguale a 0011

ma per

1101 0101

è ok come il risultato è 0101

controlli script che maschera è stata impostata nel decimale. Forse qualcuno avrà bisogno:

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

Credo che il primo esempio che si dà più controllo di ciò che esattamente i permessi un utente. Nella seconda avete appena un utente 'livello'; presumibilmente più elevati livelli erediterà tutte le autorizzazioni concesse a un utente più basso 'livello', in modo da non avere tale controllo accurato.

Inoltre, se ho ben capito, la riga

if($user_permission_level === 4)

significa che solo gli utenti con esattamente livello di autorizzazione di 4 hanno accesso all'azione - sicuramente si vorrebbe verificare che gli utenti hanno almeno che livello?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top