[php5]authentication manager

Contenu du snippet

Quelques classes largement insprirées du framework prado mais taillées pour l'utilisation hors framework (quoique).
Il inclut des notions objet d'Applis et de modules:
j'tez-y un oeil pourvu qu'vous ne l'perdiez pas :).
PS: ce code est encore améliorable. C'est Juste pour le principe.

Source / Exemple :


--Sql
CREATE TABLE `groups` (
  `id` smallint(5) unsigned NOT NULL auto_increment,
  `name` varchar(32) collate utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;

-- 
-- Contenu de la table `groups`
-- 

INSERT INTO `groups` (`id`, `name`) VALUES 
(3, 'admin');

-- --------------------------------------------------------

-- 
-- Structure de la table `permissions`
-- 

CREATE TABLE `permissions` (
  `id` smallint(5) unsigned NOT NULL auto_increment,
  `page` varchar(64) collate utf8_unicode_ci default NULL,
  `selector` enum('user_id','group_id') collate utf8_unicode_ci default NULL,
  `value` smallint(5) unsigned default NULL,
  `allowed` enum('','1') collate utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `selector` (`selector`,`value`,`page`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=28 ;

-- 
-- Contenu de la table `permissions`
-- 

INSERT INTO `permissions` (`id`, `page`, `selector`, `value`, `allowed`) VALUES 
(27, 'test.php', 'group_id', 3, '1');

-- --------------------------------------------------------

-- 
-- Structure de la table `users`
-- 

CREATE TABLE `users` (
  `id` smallint(5) unsigned NOT NULL auto_increment,
  `group_id` smallint(5) unsigned NOT NULL,
  `person_id` smallint(5) unsigned default NULL,
  `name` varchar(32) collate utf8_unicode_ci NOT NULL,
  `password` varchar(64) collate utf8_unicode_ci default NULL,
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;

<?php
/**
dataSource Path

  • /
$dsPath='../datasource'; /** DataSource File Class Name
  • /
require_once $dsPath.'/CDataSource.php'; class propertyException extends Exception { const MSG_STRING_REQUIRED='type string attendu'; const MSG_INT_REQUIRED='type int attendu'; const MSG_DATASOURCE_REQUIRED='type CDataSource attendu'; const MSG_USERMANAGER_REQUIRED='type userManager attendu'; const MSG_USER_REQUIRED='type user attendu'; const MSG_BOOL_REQUIRED='type booléen attendu'; const MSG_OBJECT_REQUIRED='mauvais type attendu'; } class getsetException extends Exception { const MSG_PORPERTY_NOT_EXIST='Propriété inexistante'; } class propertyChecker { public static function ensureString($data) { if (! is_string($data)) throw new propertyException(propertyException::MSG_STRING_REQUIRED); else return $data; } public static function ensureInt($data) { return (int)$data; } public static function ensureBool($data) { if (! is_bool($data)) throw new propertyException(propertyException::MSG_BOOL_REQUIRED); else return $data; } public static function ensureCDataSource($data) { if (! is_subclass_of(get_class($data),'CDataSource')) throw new propertyException(propertyException::MSG_CDATASOURCE_REQUIRED); else return $data; } public static function ensureUserManager($data) { if (get_class($data) != 'userManager') throw new propertyException(propertyException::MSG_USERMANAGER_REQUIRED); else return $data; } public static function ensureUser($data) { if (get_class($data) != 'user') throw new propertyException(propertyException::MSG_USERMANAGER_REQUIRED); else return $data; } } class application { private static $_app; private static $_curUser = null; private static $_curPage = null; public static function setApp($app) { self::$_application = $application; } public static function getApp($app) { return self::$_application; } public static function setPage($page) { self::$_curPage = propertyChecker::ensureString($page); } public static function getPage($page) { return self::$_curPage; } public static function createComponent($type) { if (is_subclass_of($type,'component')) { if(($n = func_num_args()) > 1) { $args = func_get_args(); $s = '$args[1]'; for($i = 2 ; $i<$n ; ++$i) $s.=",\$args[$i]"; if ($type!='securityApp') eval("\$component=new $type($s);"); else eval("\$component=securityApp::getInstance($s) ;"); return $component; } else return new $type; } else throw new Exception ('La classe '.$type.' est inexistante'); } public static function setCurrentUser($user) { self::$_curUser = propertyChecker::ensureUser($user); } public static function getCurrentUser() { return self::$_curUser; } } class component { public function __set($prop,$value) { $set='set'.$prop; if (!method_exists($this,$set)) throw new propertyException(getsetException::MSG_PORPERTY_NOT_EXIST); return $this->$set($value); } public function __get($prop) { $get='get'.$prop; if (!method_exists($this,$get)) throw new propertyException(getsetException::MSG_PORPERTY_NOT_EXIST); return $this->$get(); } } class securityApp extends component { public static $_instance=null; private $_curUser=null; private $_curPage=null; private $_modules=array(); const MODULE_DBHANDLER = 0; const MODULE_USERMANAGER = 1; const MODULE_AUTHMANAGER = 2; protected function __construct($db,$modules) { $this->_modules[self::MODULE_DBHANDLER] = $db; foreach ($modules as $key=>$subModules) { switch ($key) { case self::MODULE_USERMANAGER : $this->_modules[self::MODULE_USERMANAGER] = new userManager($this->_modules[self::MODULE_DBHANDLER],$subModules[0],$subModules[1]); break; case self::MODULE_AUTHMANAGER: $this->_modules[self::MODULE_AUTHMANAGER] = new authManager($this->_modules[self::MODULE_DBHANDLER],$subModules[0]); break; } } } public function getModule($key) { return $this->_modules[$key]; } public function getCurrentUser() { return application::getCurrentUser(); } public function setCurrentUser($object) { application::setCurrentUser($object); } public static function getInstance($db,$modules) { if (!isset(self::$_instance)) self::$_instance = new self($db,$modules); return self::$_instance; } } class session extends component { private $_sessionId; public function __construct() { } } class userManager extends component { /** property Db ressource instance
  • /
private $_dbInstance; /** property user table
  • /
private $_userTable; /** property group table
  • /
private $_groupTable; public function __construct($dataSource,$userTable,$groupTable) { $this->_dbInstance = propertyChecker::ensureCDataSource($dataSource); $this->_userTable = propertyChecker::ensureString($userTable); $this->_groupTable = propertyChecker::ensureString($groupTable); } public function isValid($name,$password) { if (is_null($password) || $password === '') return false; $this->_dbInstance->query( 'SELECT name, password '. 'FROM '.$this->_userTable.' '. 'WHERE name="'.$name.'" AND password="'.$password.'"' ); if ($row=$this->_dbInstance->fetch_assoc()) { if (is_null($row['password'])) return false; return ($row['name'] == $name && $row['password'] == $password); } return false; } /** return user object
  • /
public function getUser($name) { $users = array(); $this->_dbInstance->query('select u.id,u.group_id,g.name from '.$this->_userTable.' as u, '.$this->_groupTable.' as g where u.group_id=g.id and u.name="'.$name.'"' ); if ($row = $this->_dbInstance->fetch_assoc()) { $user = new user($this); $user->IsAnonymous = false; $user->Name = $name; $user->Group = $row['name']; $user->UserId = $row['id']; $user->GroupId = $row['group_id']; } if($this->_dbInstance->num_rows() === 0) { $user = new user($this); } application::setCurrentUser($user); return $user; } public function setUserTable($usertable) { $this->_userTable = propertyChecker::ensureString($userTable); } public function setGroupTable($groupTable) { $this->_groupTable = propertyChecker::ensureString($groupTable); } public function getUserTable() { return $this->_userTable; } public function getGroupTable() { return $this->_groupTable; } } class user extends component { private $_userManager; private $_userId; private $_name; private $_group; private $_groupId; private $_isAnonymous; public function __construct($userManager) { $this->_userManager = propertyChecker::ensureUserManager($userManager); $this->_isAnonymous = true; $this->_name = 'Anonymous'; $this->_group = 'Anonymous'; } public function setName($value) { $this->_name = propertyChecker::ensureString($value); } public function getName() { return $this->_name; } public function setGroup($value) { $this->_group = propertyChecker::ensureString($value); } public function getGroup() { return $this->_group; } public function setGroupId($value) { $this->_groupId = propertyChecker::ensureInt($value); } public function getGroupId() { return $this->_groupId; } public function setUserId($value) { $this->_userId = propertyChecker::ensureInt($value); } public function getUserId() { return $this->_userId; } public function setIsAnonymous($value) { $this->_isAnonymous = propertyChecker::ensureBool($value); } public function getIsAnonymous() { return $this->_isAnonymous; } } class authManager extends component { private $_permTable; private $_dbInstance; public function __construct($db,$permT) { $this->_permTable = $permT; $this->_dbInstance=$db; } public function isAuthorized($page,$user) { $this->_dbInstance->query('SELECT `allowed` FROM `'.$this->_permTable.'` WHERE ' . '(`page`="'.$page.'" OR `page` IS NULL) ' . 'AND (' . '(`selector`="user_id" AND `value`="'.$user->UserId.'") ' . 'OR (`selector`="group_id" AND `value`="'.$user->GroupId.'") ' . ')' . 'ORDER BY `page` DESC'); $result=$this->_dbInstance->fetch_assoc(); if ($result && $result['allowed']==='1') { return true; } else return false; } } /** Instanciation de la DB
  • /
//Classe perso dispo sur CS $DbClass='CMysql'; $DbHost='localhost'; //Ca c'est affaire de gout, je le conçois, moi, c'est mon idole!! //Au passage désolé pour le dérangement. $DbUser='SiTuAimesBienRaffarinTapesDansTesMains'; $DbPass='SiTuAimesAntoineSeillereTapesParTerre'; $DbName='db_auth'; /** Ou $Db = votre instance de votre propre DB à condition votre Db ait les methodes query et fetch_assoc (voir code)
  • /
$db=CDataSource::add($DbClass,$DbHost,$DbUser,$DbPass,$DbNam); /** Définition des 2 modules de l'application => le nom des tables de la db par module
  • /
$modules=array(securityApp::MODULE_USERMANAGER=>array('users','groups'), securityApp::MODULE_AUTHMANAGER=>array('permissions')); /** Instanciation de l'appli de gestion des droits
  • /
$App=application::createComponent('securityApp',$db,$modules); /** Récupération du module userManager
  • /
$UserManager=$App->getModule(securityApp::MODULE_USERMANAGER); /** Vérification de la validité de l'utilisateur ici sans cryptage pour l'exemple
  • /
$userName='youruser'; $uesrPwd='yourpwd'; if ($UserManager->isValid($userName,$userPwd)) { if (!is_null ($App->CurrentUser)) echo $App->CurrentUser->Name; else echo 'utilsateur indéfini'; $user=$UserManager->getUser($userName); if (!is_null ($App->CurrentUser)) echo $App->CurrentUser->Name; else echo 'utilsateur indéfini'; $testUser= $App->getModule(securityApp::MODULE_USERMANAGER)->getUser($userName)->GroupId; if (!is_null ($App->CurrentUser)) echo $App->CurrentUser->Name; else echo 'utilsateur indéfini'; echo $testUser; // Vérification de la permission $auth=$App->getModule(securityApp::MODULE_AUTHMANAGER)->isAuthorized('test1.php',$App->CurrentUser); if ($auth===true) echo 'Accès autorisé'; else echo 'Accès Non Autorisé'; } else echo 'utilisateur invalide'; ?>

Conclusion :


On peut utiliser n'importe quelle classe de DB :
Il faut juste seulement modifier la methode ensureCDataSource de la classe propertyChecker avec le nom de votre classe utilisée et que votre classe implémente les methodes query et fetch_assoc:
J'essaierai ultérieurement de définir une interface dans ce but.
Manque aussi le cryptage. C'est ceci-dit un bon exercice que de l'ajouter

A voir également

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.