Squelette de gestion des droits

Soyez le premier à donner votre avis sur cette source.

Snippet vu 10 036 fois - Téléchargée 16 fois

Contenu du snippet

Ca faisait longtemps que je n'avais pas posté quelque chose...alors zou...
Ce code est plutôt un prétexte : un post sur le forum posait des questions sur les opérateurs bit à bit. Je me suis dit "tien, c'est vrai qu'ils sont peu utilisés, et donc peu connus, par la plupart des codeurs PHP". J'ai donc décidé de faire un code prétexte, servant d'exemple pour une utilisation de ces opérateurs.
Ce code est néanmoins implémentable et extensible, donc utilisable (à condition de l'étendre hein...). Et il ne prétend pas détenir LA solution pour gérer des droits : c'est une solution comme une autre...elle a ses avantages et ses inconvénients.
Mais d'abord, les opérateurs bit à bit...le code n'en montrera qu'un, donc une petite explication préalable est nécessaire:
Pour rappel, on lit les bits de droite à gauche, le bit le plus faible se trouvant à droite, et le plus fort à gauche.
Du coup, pour comparer 10 et 110, on peut aussi lire : 010 et 110.
Les opérateurs :
AND ou & : les bits qui sont à 1 dans l'argument de gauche et de droite sont mis à 1
101 & 111 = 101
110 & 10 = 10
101 & 10 = 0
OR ou | : les bits qui sont à 1 dans l'argument de gauche ou de droite sont mis à 1
101 | 111 = 111
110 | 10 = 110
101 | 10 = 111
XOR ou ^ : les bits qui sont à 1 dans l'argument de gauche ou dans l'argument de droit mais pas dans les deux arguments en même temps sont mis à 1
101 ^ 111 = 10
110 ^ 10 = 100
101 ^ 10 = 111
NOT ou ~ : les bits à 1 dans l'argument sont mis à 0, et inversement :
~ 100 = 11111111111111111111111111111011 (et oui, on est sur 32 bits!)
le Shift left ou << : décale les bits de l'argument de gauche X fois (ou X est l'argument de droite) vers la gauche. Cela revient à multiplier par 2 à chaque fois
100 << 2 = 10000
Ou avec des entiers :
1 << 2 = 4 (en binaire : 1 (ou 001 donc) << 2 = 100)
Le shift right, ou >> décale les bits de l'argument de gauche X fois (ou X est l'argument de droite) vers la droite. Cela revient à diviser par 2 à chaque fois
100 >> 2 = 1 (ou 001 donc)
Ou avec des entiers :
4 >> 1 = 2 (en binaire : 100 >> 1 = 10 (ou 010))

Facile, non ?
Ce code va utiliser le | pour vérifier des droits. Le principe est très simple une fois que vous avez compris le fonctionnement des opérateurs bit à bit.
On imagine, pour ce code, que l'on crée la gestion des messages d'un forum, par exemple.
On a 3 types d'utilisateurs :
le visiteur, qui n'a que le droit de lire les messages
le membres, qui peut lire les messages et en écrire de nouveau
l'administrateur, qui peut lire, écrire, mais aussi éditer des messages existants.

On affecte donc des niveaux de droit aux 3 accès :
1 pour lire
10 pour écrire
100 pour éditer

Et on fixe les accès des utilisateurs :
1 pour le visiteur
11 pour le membre
111 pour l'administrateur

Et c'est tout :-)
A noter que decbin() permet de transformer un entier en octets: 4 devient alors 100 (sous forme de chaîne...on ne peut pas écrire directement en binaire en php), et que bindec fait l'inverse : il prend une chaîne représentant un nombre binaire, et le transforme en son équivalent entier : 100 devient 4.

Pour les droit, on pourrait aussi utiliser des entiers :
1 pour lire
2 pour écrire
4 pour éditer
et
1 pour le visiteur
3 pour le membre
7 pour l'administrateur

mais c'était plus parlant avec des bits, pour suivre la petite explication :-) Ceci dit, les entiers seraient plus performants, car on n'aurait alors pas besoin de passer par decbin() et bindec().

Source / Exemple :


<?php
abstract class rights {
	protected $bRights = '0';
	
	public function __get($sProp) {
		switch($sProp) {
			case 'RIGHTS':
				return $this->bRights;
			default:
				throw new Exception('Cannot get property '.$sProp);
		}
	}
}

class read extends rights {
	protected $bRights = '1';
}

class write extends rights {
	protected $bRights = '10';
}

class edit extends rights {
	protected $bRights = '100';
}

abstract class user {
	protected $bRights = '0';
	
	public function hasRights(rights $rights) {
		return (decbin(bindec($rights->RIGHTS) | bindec($this->bRights)) === $this->bRights); 
	}
}

class visitor extends user {
	protected $bRights = '1';
}

class member extends user {
	protected $bRights = '11';
}

class admin extends user {
	protected $bRights = '111';
}

$read = new read;
$write = new write;
$edit = new edit;

$visitor = new visitor;
echo (int)$visitor->hasRights($read),"\n";
echo (int)$visitor->hasRights($write),"\n";
echo (int)$visitor->hasRights($edit),"\n";

$member = new member;
echo (int)$member->hasRights($read),"\n";
echo (int)$member->hasRights($write),"\n";
echo (int)$member->hasRights($edit),"\n";

$admin = new admin;
echo (int)$admin->hasRights($read),"\n";
echo (int)$admin->hasRights($write),"\n";
echo (int)$admin->hasRights($edit),"\n";
?>

Conclusion :


A noter que l'on peut modifier la méthode user::hasRights() pour utiliser le & :
return (decbin(bindec($rights->RIGHTS) & bindec($this->bRights)) === $rights->RIGHTS);

A voir également

Ajouter un commentaire

Commentaires

Betamax
Messages postés
2
Date d'inscription
mercredi 15 février 2006
Statut
Membre
Dernière intervention
23 décembre 2008
-
Malalam : J'utilise dans un système de gestion de droits le même principe à part le faite de comparer les droits user avec un mask binaire (droits par défaut) comme le fait le pingouin (UNIX) et un droit pour chaque document :)
de cette façon je pousse un peu plus loin dans le degrés d'autorisation.
Je me lance dans les designs pattern (d'ailleurs tu as posté de très bon tuto :) ) mais but dans la manière de procéder pour la construction de divers objets différent (factory) avec accès à plusieurs tables (multiton) et gestion des droits pour certains objets (masque binaire) (user , image ,file etc...)... dur dur.
surtout que je n'ai pas beaucoup de temps :(
merci @ bientôt
malalam
Messages postés
10844
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
'lut Akhe, merci :-)

Betamax : dans un environnement "simple", en restant à 1 niveau de droits, on reste bloqués à 32 possibilités (à moins d'avoir un serveur 64 bits évidemment). Ca n'empêche pas de moduler tout ça : un module, 32 droits...donc un projet, X fois 32 droits. Ca devrait suffire...
Utilisation des objets : ça fait potentiellement bcp d'objets, et ce n'est pas forcément optimal en terme de perf. Tout dépend de la façon dont s'est utilisé...et de savoir si la légère perte en perf vs la très large "scalability", l'évolutivité, etc...n'en vaut pas la chandelle, au final (moi, je suis un convaincu...).
Les droits "binaires", c'est bien, mais on s'y perd vite si on ne gère pas ça correctement (bordel, 100101 ça correspond à QUOI????). Pareil pour les entiers (hmmm...57, donc...voué voué voué...le gars y peut s'logger...ah non, c'est de l'écriture pplus du log plus l'accès en consultation à cette partie du module...ah nan...merde, chais plus).
C'est difficile à débugger pour la même raison.
Enfin, en l'état, c'est insuffisant. Enfin...c'est suffisant pour un petit projet, ça ne l'est pas pour un gros. Il faut moduler plus, réfléchir intensément aux accès, aux groupes d'accès, aux profils utilisateur etc...et faire bien les choses de manière à pouvoir ajouter de nouveaux types d'accès par la suite. Mais ça...c'est après tout le lot commun de tout gros projet :-)

Globalement, je pense que la gestion des droits via les opérateurs binaires est plutôt une approche performante. Et elle est élégante, et permet une programmation "agile" si on s'y prend bien. Mais il y a d'autres solutions...
aKheNathOn
Messages postés
285
Date d'inscription
dimanche 22 juillet 2001
Statut
Modérateur
Dernière intervention
5 décembre 2013
-
lut malalam, j'adore ce genre de source ;)
Betamax
Messages postés
2
Date d'inscription
mercredi 15 février 2006
Statut
Membre
Dernière intervention
23 décembre 2008
-
salut ;)
par cette note ,je voudrai simplement dire bravo à notre cher malalam que nous apprécions beaucoup mais ça serai cool si tu nous disait ou son les inconvénients dans cette approche .
merci également à CS et à tous ceux qui y contribuent .
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Plop,

@Opossum_farceur : c'est presque trop technique pour moi... Presque, hein... Disons que j'ai tellement peu l'habitude d'utiliser les opérateurs sur les bits, que j'ai un peu de mal à me représenter quel est le résultat, quand m'en servir et surtout, comment ça marche...
Comment ça marche, je sais : quand je mets sur papier... Faut que je fasse des tableaux, tout ça... Je m'embrouille vite... Donc je plussoie au commentaire de Malalam : un petit tuto, ça pourrait être une super bonne idée, parce qu'effectivement, j'en étais arrivé à la même conclusion que lui quant à l'utilisation des opérateurs de bits par les jeunes développeurs.

@Malalam : pour la mail, je viens de m'y coller... C'est à ton tour. ^^
Sinon, excuse-moi d'avoir soulevé le point que tu ne souhaitais pas aborder lol Je prends ça comme un compliment sur ce coup là :) Et... Cette discussion naissante sur ce sujet que tu ne voulais pas montrer, ben... Ca confirme le bien fondé de notre projet (pu*$€ ça fait pas un an qu'on a commencé à en parler, mais pas loin !)

Allez, zou, bonne soirée à tous !

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.