Gérer ses droits et accès utilisateurs en PHP : le Bit Bashing

Encore un problème récurrent du développeur: dans un CMS, on a une admin avec 10 utilisateurs qui ont avoir des rôles différents, chaque rôle étant autorisé à faire une certaine liste d’actions…
La solution “facile” (et malheureusement, celle qu’on voit quasiment TOUJOURS appliquée) est de créer une table contenant une colonne dans la base de données pour chaque action, plus un champ “user_ID”. Avec nos 4 actions, on a donc une table de 5 champs, qu’on mettra à 0 ou 1 selon que l’utilisateur peut effectuer l’action ou pas.

Problèmes: si on crée une nouvelle action demain, par exemple “éditer la catégorie du post”, on se retrouve avec un schéma de base de donnée à mettre à jour, pour ajouter un champ. Même chose si une action n’existe plus (par exemple si on en regroupe deux: “si on peut valider un post, on pourra aussi toujours l’éditer”). De plus, avec un grand nombre d’utilisateurs et/ou un grand nombre d’actions, on se retrouve avec une table énorme, simplement pour gérer qui peut faire quoi.

Une solution plus élégante serait d’utiliser le Bit Bashing. Cette technique, utilisée pour la gestion des droits sous Unix, permet de regrouper tous les droits d’un utilisateur en UN SEUL chiffre. Pour arriver à cela, chaque action est associée à un nombre, qu’on ne choisit pas au hasard: la suite des nombres est la suite des puissances de 2… Une de ses propriétés mathématiques est que chaque nombre est égal à la somme de tous les précédents, à laquelle on ajoute 1. On a donc bien : 1, 2 (1+1), 4 (2+1+1), 8 (4+2+1+1), 16 (8+4+2+1+1), 32 (16+8+4+2+1+1)…

Sous Unix, voici comment le “nombre” des accès (Lire, Ecrire, Executer) est calculé :
Executer : 1
Ecrire : 2
Lire : 4
(pour une quatrième action, on aurait pris 8, etc)
Puisque chaque nombre est égal à la somme des précédents plus un, on peut ajouter les valeurs sans jamais tomber avec 2 combinaisons différentes sur le même nombre. Par exemple, 5 ne peut être que 4+1, 6 ne peut être que 4+2, 7 ne peut être que 4+2+1.
Pour calculer la valeur de l’accès, on n’a donc qu’à ajouter les valeurs des actions qu’on autorise. Par exemple, pour Lis et Execute (mais n’écris pas), on aura Lis (4) + Execute (1) = 5 (c’est comme ça qu’on calcule le nombre de la commande CHMOD, rien de bien nouveau).

En PHP, on manipule directement les bits (d’où l’utilisation de la notation en base 2) pour profiter des possibilités de comparaisons bit à bit:

  1. define(‘EXECUTER’, 1<<0);
  2. define(‘ECRIRE’, 1<<1);
  3. define(‘LIRE’, 1<<2);
  4.  
  5. $user_rights = 5;
  6. if (LIRE & $user_rights) { echo "LIRE<br>"; } // true
  7. if (ECRIRE & $user_rights) { echo "ECRIRE<br>";} // false
  8. if (EXECUTER & $user_rights) { echo "EXECUTER<br>"; } // true

On aura “LIRE / EXECUTER”. Bien sur, $user_rights doit être pioché dans une base de données ou autre. Avec $user_rights = 4, on aurait eu “LIRE / ECRIRE”, etc.

Et vous, vous faisiez comment, avant de découvrir le Bit Bashing ? ;)

Partager: Ces icones representent les sites de bookmarking social dans lesquels vos lecteurs peuvent partager et faire découvrir vos pages.
  • Technorati
  • Digg
  • Digg France
  • DiggFR.com
  • del.icio.us
  • blogmarks
  • Scoopeo
  • Wikio
  • YahooMyWeb

A lire aussi

6 Responses to “Gérer ses droits et accès utilisateurs en PHP : le Bit Bashing”

  1. [...] on peut, notamment, stocker un niveau d’accès pour chaque utilisateur (et utiliser le Bit Bashing…) Partager: Ces icones representent les sites de bookmarking social dans lesquels vos [...]

  2. Ah cool,

    Merci pour ce tuto !

  3. [...] Bon, certes, j’ai pris pas mal de raccourcis, donc le code n’est pas vraiment exploitable “tel quel”, mais avouez que la classe est efficace dans le sens où elle peut gérer toutes sortes d’objets. Il faudrait notamment ajouter, avec __set, le système qui vérifie que le champ existera dans la table (en récupérant son type pour faire des contrôles avant d’insérer). Dans le __destruct, il faut faire en sorte de ne sauver que les champs ayant été modifiés. Et bien sur, éviter l’édition de l’ID sur un objet que l’on vient de charger. Tout un programme On pourrait par exemple utiliser ce système pour gérer les utilisateurs d’un site, avec gestion des droits en bit bashing. [...]

  4. Très bonne mise en pratique ;)

  5. J’avoue que j’aurais pas pensé le faire comme ça..
    Merci pour l’astuce :)

  6. Article très intéressant, merci.

Discussion Area - Leave a Comment