begin process at 2010 02 10 16:54:55
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > SQUELETTE DE GESTION DES DROITS

SQUELETTE DE GESTION DES DROITS


 Information sur la source

Note :
9,33 / 10 - par 3 personnes
9,33 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Astuces Classé sous :binaire, bit, droits, opérateurs Niveau :Initié Date de création :19/12/2008 Date de mise à jour :19/12/2008 19:47:21 Vu :2 670

Auteur : malalam

Ecrire un message privé
Site perso
Commentaire sur cette source (9)
Ajouter un commentaire et/ou une note

 Description

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

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


 Historique

19 décembre 2008 19:41:25 :
Ajout d'explications
19 décembre 2008 19:47:21 :
re ajouts...:-)

 Sources du même auteur

Source avec Zip ASTUCES/HACK PHP
[PHP 5.1] CLASS STRING : NOUVEL EXEMPLE SUR LA SPL
Source avec Zip Source avec une capture [PHP 5.1] PHOTOPHOP (PHPDRAW 2)
Source avec Zip Source avec une capture [PHP5.1] O-LOC : CLASSE ET BACKOFFICE D'INTERNATIONALISATION
Source avec Zip [PHP5] EXCEPTIONERROR PACKAGE : TRANSFORMER TOUTES LES ERREU...

 Sources de la même categorie

Source avec une capture PAGINATION EN PHP par Orangina
Source avec Zip POO - DEBUGGER par DiGhan
Source avec Zip CRAWLER DE SITE EN PHP par Mcjo
DÉCOUPAGE D'UN TEXTE EN FONCTION DES SAUTS DE LIGNES par biloubil
RÉCUPÉRER LE CHEMIN RELATIF D'UN OBJET PAR RAPPORT À LA RACI... par FredPsy

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture CONVERTISEUR BINAIRE OCTAL DEC HEX... par sitajony
Source avec Zip CONVERTISSEUR DE BASE DÉCIMALE, BINAIRE, HEXADÉCIMAL, ... par nicof3
Source avec Zip Source avec une capture CAPTCHA ANTI-BOT + FICHIER SON (WAV) par nax333
CLASSE CHMOD par tex73
[PHP5]AUTHENTICATION MANAGER par guill76

Commentaires et avis

Commentaire de DiGhan le 20/12/2008 17:38:25 9/10

L'idée est très bonne. C'est simple et facile à utiliser.

En complément (dans le fond exactement pareil mais qui présente des subtilités) :

<?php

define('RIGHT_READ' , 1);
define('RIGHT_WRITE', 2);
define('RIGHT_EXEC' , 4);

abstract class User
{
protected $iRights = 0;

public function isAllowedToRead() {
   return (($this->iRights & RIGHT_READ) === RIGHT_READ);
}

public function isAllowedToWrite() {
return (($this->iRights & RIGHT_WRITE) === RIGHT_WRITE);
}

public function isAllowedToExec() {
return (($this->iRights & RIGHT_EXEC) === RIGHT_EXEC);
}
}

class Guest extends User
{
    public function __construct() {
     $this->iRights = RIGHT_READ;
    }
}

class Member extends User
{
    public function __construct() {
        $this->iRights = RIGHT_READ | RIGHT_WRITE;    
    }
}

class Admin extends User
{
    public function __construct() {
        $this->iRights = RIGHT_READ | RIGHT_WRITE | RIGHT_EXEC;    
    }
}

$oGuest  = new Guest;
$oMember = new Member;
$oAdmin  = new Admin;

var_dump($oGuest->isAllowedToRead());
var_dump($oGuest->isAllowedToWrite());
var_dump($oGuest->isAllowedToExec());

var_dump($oMember->isAllowedToRead());
var_dump($oMember->isAllowedToWrite());
var_dump($oMember->isAllowedToExec());

var_dump($oAdmin->isAllowedToRead());
var_dump($oAdmin->isAllowedToWrite());
var_dump($oAdmin->isAllowedToExec());

?>

Commentaire de neigedhiver le 20/12/2008 21:12:53

Plop,

Salut Boss, ça fait un bail !
Ca me fait plaisir de voir que je suis pas tout seul à utiliser les opérateurs binaires pour gérer des droits... Je les ai découvert dans phorum.org , alors que phpBB (j'étais très forum à l'époque...) utilisais un système très peu évolutif (et qui ne me semble pas avoir été beaucoup amélioré avec la version 3, mais là n'est pas la question).

Par contre, j'apprécie l'utilisation d'objets pour chaque permission... C'est une approche à laquelle je n'avais pas pensé (merci donc de l'avoir fait pour moi). Ca me perturbe un peu, d'ailleurs... En même temps, c'est bien plus Orienté Objet... Plus qu'avec des constantes (je ne critique pas, hein, puisque j'ai tendance à utiliser des constantes également...).
Du coup... Si on veut gérer davantage de permissions (parce que là, c'est quand même archi simple), ça fait autant de classes que de permissions... Cependant (c'est un sujet à creuser) on doit pouvoir utiliser des classes plus complexes (héritages, tout ça tout ça)... C'est une approche qui me plait, quoi...
C'est vrai que si j'utilise pas mal d'objets, finalement, je n'en utilise peut-être pas suffisament...

Commentaire de opossum_farceur le 21/12/2008 01:50:48

Hi!,

Petite piqure de rappel (indolore!) sur les "masques".
En considérant que le bit de poids faible a le rang 0,

Lecture du bit $bit de la variable $var :
echo ($var>>$bit)&1;

Mise à 1 du bit $bit de la variable $var :
$var|=(1<<$bit);

Mise à 0 du bit $bit de la variable $var :
$var&=~(1<<$bit);

Commentaire de malalam le 21/12/2008 12:05:59 administrateur CS

Hey :-)

Salut Olivier!
Ca fait un bail en effet...je suis toujours à ta dispo pour notre petit projet, dès que tu auras le temps (j'en manque aussi, rassure-toi...plus que jamais!)

Bon...
Dighan : alternative sympa en effet! Merci pour ta contribution. Elle a le mérite de montrer un peu plus l'utilisation des opérateurs "bitwise". Et elle est plus courante que la mienne :-)

Opossum_farceur : merci aussi pour ta contribution, et ce rappel...qui risque d'être une sacrée nouveauté pour beaucoup :-) Je me suis mal exprimé quand je disais "peu utilisés [les opérateurs bit à bit] par la plupart des codeurs php" : j'aurais dû préciser les codeurs débutants, voire amateurs. Et du coup, je serais toi, j'expliquerais un peu plus tout ça...un tuto serait peut-être le bienvenue, avec des exemples appliqués concrets, sur l'utilisation de ces opérateurs.

Neige : un chtit mail ? :-) Ceci dit : je m'oriente de plus en plus vers les projets composés de nombreuses classes, dont beaucoup sont petites et utilitaires, plus quelques moteurs utilisant ces classes utilisateur. Je me rends compte que c'est bien plus facile à faire évoluer et à utiliser que des projets composés de grosses classes qui font tout...je t'enverrai un exemple d'un framework que j'ai monté il y a peu (et que je ne peux pas mettre ici...car il est vendu, et cher, par ma boîte, aussi je compte sur ton intégrité :-) garde le pour toi!) et qui montre mon orientation objet. En effet, ici ce n'est qu'un squelette, et en utilisation réelle, les classes doivent être remplies un peu plus. En fait je vais même plus loin, en utilisation réelle...je complèterai sans doute un jour, mais sur un projet plus concret que je peux divulguer ici. Le but étant, dans un environnement complexe de type ERP, avec énormément d'utilisateurs aux profils très différents, de gérer facilement leurs accès, et d'inventer de nouveaux profils au fil de l'eau.
Bref, ce choix de code "prétexte" n'était pas si anodin que ça :-) C'est une vraie réflexion de ma part ces temps-ci...et tu as vu ce que je ne comptais pas montrer au fond : je pensais qu'on allait se concentrer sur les opérateurs "bitwise", car c'est le but de ce code sur phpcs, mais au fond, il y a autre chose, pour moi... :-)

Commentaire de neigedhiver le 21/12/2008 19:14:09

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 !

Commentaire de Betamax le 22/12/2008 08:41:12 9/10

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 .

Commentaire de aKheNathOn le 22/12/2008 13:19:55 10/10

lut malalam, j'adore ce genre de source ;)

Commentaire de malalam le 22/12/2008 21:49:11 administrateur CS

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

Commentaire de Betamax le 23/12/2008 00:59:47

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

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Enregistrer un binaire dans une base de données [ par astien ] astienComment fais-ton en php pour inserer un resgistre avec un objet binaire ?Quelqu'un peut m'aider ? V péter un plomb (pb de droits inside) [ par Mamienova ] Bonsoir a tous je suis depuis cet apres-midi sur un pu*ù$^ù*^de probleme de *ù$*^*^ù*^. Bon alors pour faire simple : je veux uploader des images sur mkdir et droits [ par elanspeech ] salut, dans ma page php, je fais la commande suivante : mkdir ("rep/", 0777); le repertoire est bien cree mais pas avec les bons droits.... j'obtiens droits sur fichiers [ par cas ] Voila ce que j'ai fait pour créer un nouveau fichier dans le réertoire chez l'hébergeur.&lt;?phpif (!$fp = fopen("toto.txt","w+")) { print "Cannot droits sur fichiers [ par brok ] comment dois je m'y prendre pour changer les droits sur les fichiers qui se trouvent sur le seveur web(free).Par ftp ca ne fonctionne pas...Et puis c' Comparaison Binaire [ par 6Po ] Bonjour,J'aimerais effectué une comparaison binaire. 6 = 110 2 = 010 Donc normal 6 & 2 devrait faire 010 (soit 2)... si j'effectue le test suivant if Sécurité pour un script de commentaires !!! et droits d'auteur?? [ par perig ] BonjourJe suis désolé, je n'ai pas fini de vous embêter avec mes questions !!!! Voilà la question du jour :J'ai crée un script qui pe image dans mysql sous forme binaire ! [ par fmazoue ] bonjour mon pb c que j'ai enregistré des image jpeg dans ma base de donnée sous forme binaire (blob)et que je voudrai maintenant recuperer ces images image dans mysql sous forme binaire ! [ par fmazoue ] bonjour mon pb c que j'ai enregistré des image jpeg dans ma base de donnée sous forme binaire (blob)et que je voudrai maintenant recuperer ces images Envoie de SMS Gratuit, Illimité par tt ds le monde - 2.07.2004 [ par tkof ] Tout d'abord bonjour à tous !Il y a un an de cela j'ai develloper une application en php me permettant l'envoie de sms gratuit et illimité sur environ


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,170 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales