| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- <?xml version="1.0" encoding="utf-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.auth.adapter.dbtable">
- <title>Authentification avec une table de base de données</title>
- <sect2 id="zend.auth.adapter.dbtable.introduction">
- <title>Introduction</title>
- <para>
- <classname>Zend_Auth_Adapter_DbTable</classname> fournit la possibilité d'authentifier
- sur la base de crédits stockés dans une table de base de données. Comme
- <classname>Zend_Auth_Adapter_DbTable</classname> requiert qu'une instance de
- <classname>Zend_Db_Adapter_Abstract</classname> soit fournie à son constructeur, chaque
- instance est liée à une connexion de base de données particulière. Les autres options
- de configuration peuvent être réglées grâce au constructeur ou au travers de
- différentes méthodes, une pour chaque option.
- </para>
- <para>
- Les options de configuration disponibles incluent :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis><property>tableName</property></emphasis> : il s'agit du nom de
- la table dans la base de données qui contient les crédits d'authentification,
- et envers laquelle la requête d'authentification sera réalisée.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis><property>identityColumn</property></emphasis> : il s'agit du
- nom de la colonne dans la table utilisée pour représenter l'identité. La
- colonne d'identité doit contenir une valeur unique, comme un "username" ou
- une adresse mail.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis><property>credentialColumn</property></emphasis> : il s'agit
- du nom de la colonne dans la table utilisée pour représenter le crédit. Dans
- le cas d'une simple authentification par identité / mot de passe, la valeur
- de crédit correspond au mot de passe. Voir aussi l'option
- <property>credentialTreatment</property>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis><property>credentialTreatment</property></emphasis> : dans la
- plupart des cas, les mots de passe et autres données sensibles sont cryptés,
- hachés, encodés, masqués, ou sinon traités à travers une fonction ou un
- algorithme. En spécifiant un traitement paramétrable de chaîne avec cette
- méthode, comme <methodname>MD5(?)</methodname> ou
- <methodname>PASSWORD(?)</methodname>, un
- développeur peut appliquer un code <acronym>SQL</acronym> arbitraire sur les
- données de crédit fournies. Comme ces fonctions sont spécifiques à chaque
- gestionnaire de base de données (<acronym>SGBD</acronym>), vérifiez le manuel
- de la base de données pour vérifier la disponibilité de ces fonctions dans
- votre système.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.auth.adapter.dbtable.introduction.example.basic_usage">
- <title>Utilisation basique</title>
- <para>
- Comme expliqué dans l'introduction, le constructeur de
- <classname>Zend_Auth_Adapter_DbTable</classname> requiert une instance de
- <classname>Zend_Db_Adapter_Abstract</classname> qui est utilisée comme connexion à
- la base de données à laquelle l'instance d'adaptateur d'authentification est liée.
- Avant tout, la connexion à la base de donnée devrait être crée.
- </para>
- <para>
- Le code suivant crée un adaptateur pour une base de données en mémoire, crée
- un schéma avec une table unique, et insère une ligne sur laquelle nous pouvons
- réaliser une requête d'authentification plus tard. Cet exemple requiert que
- l'extension <acronym>PDO</acronym> SQLite soit disponible :
- </para>
- <programlisting language="php"><![CDATA[
- // Crée une connexion de base de données SQLite en mémoire
- $dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
- ':memory:'));
- // Construit une requête de création de table
- $sqlCreate = 'CREATE TABLE [users] ( '
- . '[id] INTEGER NOT NULL PRIMARY KEY, '
- . '[username] VARCHAR(50) UNIQUE NOT NULL, '
- . '[password] VARCHAR(32) NULL, '
- . '[real_name] VARCHAR(150) NULL)';
- // Crée la table de crédits d'authentification
- $dbAdapter->query($sqlCreate);
- // Construit la requête pour insérer une ligne pour laquelle
- // l'authentification pourra réussir
- $sqlInsert = "INSERT INTO users (username, password, real_name) "
- . "VALUES ('my_username', 'my_password', 'My Real Name')";
- // Insertion des données
- $dbAdapter->query($sqlInsert);
- ]]></programlisting>
- <para>
- Avec une connexion de base de données et des données disponibles dans la
- table, une instance de <classname>Zend_Auth_Adapter_DbTable</classname> peut être
- créée. Les valeurs d'options de configuration peuvent être fournies au
- constructeur ou en tant que paramètres aux méthodes de réglage après
- l'instanciation :
- </para>
- <programlisting language="php"><![CDATA[
- // Configure une instance avec des paramètres de constructeur ...
- $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter,
- 'users',
- 'username',
- 'password');
- // ... ou configure l'instance avec des méthodes de réglage
- $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
- $authAdapter->setTableName('users')
- ->setIdentityColumn('username')
- ->setCredentialColumn('password');
- ]]></programlisting>
- <para>
- A cet instant, l'instance de l'adaptateur d'authentification est prête à
- recevoir des requêtes d'authentification. Dans le but de réaliser une requête
- d'authentification, les valeurs des crédits requêtés sont fournies à l'adaptateur
- avant d'appeler la méthode <methodname>authenticate()</methodname> :
- </para>
- <programlisting language="php"><![CDATA[
- // Règle les valeurs d'entrées des crédits
- // (en général, à partir d'un formulaire d'enregistrement)
- $authAdapter->setIdentity('my_username')
- ->setCredential('my_password');
- // Réalise la requête d'authentification, et sauvegarde le résultat
- $result = $authAdapter->authenticate();
- ]]></programlisting>
- <para>
- En plus de la disponibilité de la méthode <methodname>getIdentity()</methodname>
- pour récupérer l'objet du résultat d'authentification,
- <classname>Zend_Auth_Adapter_DbTable</classname> supporte aussi la récupération de
- la ligne de la table qui a réussi l'authentification :
- </para>
- <programlisting language="php"><![CDATA[
- // Affiche l'identité
- echo $result->getIdentity() . "\n\n";
- // Affiche la ligne de résultat
- print_r($authAdapter->getResultRowObject());
- /* Affiche:
- my_username
- Array
- (
- [id] => 1
- [username] => my_username
- [password] => my_password
- [real_name] => My Real Name
- )
- */
- ]]></programlisting>
- <para>
- Puisque la ligne de la table contient la valeur de crédit, il est important de
- garantir ces valeurs contre l'accès fortuit.
- </para>
- </example>
- </sect2>
- <sect2 id="zend.auth.adapter.dbtable.advanced.storing_result_row">
- <title>Utilisation avancée : maintenir persistant l'objet de résultat DbTable</title>
- <para>
- Par défaut, <classname>Zend_Auth_Adapter_DbTable</classname> retourne l'identité
- fournie à l'objet Auth en cas d'authentification couronnée de succès. Un autre scénario
- d'utilisation, où les développeurs veulent stocker dans le mécanisme de stockage
- persistant du <classname>Zend_Auth</classname> un objet d'identité contenant d'autres
- informations utiles, est résolu en utilisant la méthode
- <methodname>getResultRowObject()</methodname> retournant un objet
- <emphasis>stdClass</emphasis>. Le petit bout de code suivant illustre cette
- utilisation :
- </para>
- <programlisting language="php"><![CDATA[
- // authentifie avec Zend_Auth_Adapter_DbTable
- $result = $this->_auth->authenticate($adapter);
- if ($result->isValid()) {
- // stocke l'identité comme objet dans lequel seulement username et
- // real_name sont retournés
- $storage = $this->_auth->getStorage();
- $storage->write($adapter->getResultRowObject(array('username',
- 'real_name')));
- // stocke l'identité comme objet dans lequel la colonne password
- // a été omis
- $storage->write($adapter->getResultRowObject(null, 'password'));
- /* ... */
- } else {
- /* ... */
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.auth.adapter.dbtable.advanced.advanced_usage">
- <title>Utilisation avancée par l'exemple</title>
- <para>
- Bien que le but initial de <classname>Zend_Auth</classname> (et par extension celui de
- <classname>Zend_Auth_Adapter_DbTable</classname>) est principalement
- l'<emphasis>authentification</emphasis> et non
- l'<emphasis>autorisation</emphasis> (ou contrôle d'accès), il existe quelques
- exemples et problèmes qui franchissent la limite des domaines auxquels ils
- appartiennent. Selon la façon dont vous avez décidé d'expliquer votre problème, il
- semble parfois raisonnable de résoudre ce qui pourrait ressembler à un problème
- d'autorisation dans l'adaptateur d'authentification.
- </para>
- <para>
- Ceci étant dit, <classname>Zend_Auth_Adapter_DbTable</classname> possède des mécanismes
- qui sont construits de telle sorte qu'ils peuvent être démultipliés pour ajouter des
- contrôles supplémentaires au moment de l'authentification pour résoudre quelques
- problèmes communs d'utilisateur.
- </para>
- <programlisting language="php"><![CDATA[
- // La valeur du champs "etat" d'un compte
- // ne doit pas être égal à "compromis"
- $adapter = new Zend_Auth_Adapter_DbTable($db,
- 'utilisateurs',
- 'login',
- 'password',
- 'MD5(?) AND etat != "compromis"');
- // La valeur du champs "actif" d'un compte
- // doit être égal à "TRUE"
- $adapter = new Zend_Auth_Adapter_DbTable($db,
- 'utilisateurs',
- 'login',
- 'password',
- 'MD5(?) AND actif = "TRUE"');
- ]]></programlisting>
- <para>
- Un autre scénario possible est l'implantation d'un mécanisme de "salting".
- "Salting" est un terme se référant une technique qui peut fortement améliorer la
- sécurité de votre application. C'est basé sur l'idée que concaténer une chaîne
- aléatoire à tout mot de passe rend impossible la réussite d'une attaque de type "brute
- force" sur la base de données en utilisant des valeurs préalablement hashées issues
- d'un dictionnaire.
- </para>
- <para>
- Par conséquent nous devons modifier notre table pour stocker notre chaîne de
- "salt" aléatoire :
- </para>
- <programlisting language="php"><![CDATA[
- $sqlAlter = "ALTER TABLE [users] "
- . "ADD COLUMN [password_salt] "
- . "AFTER [password]";
- $dbAdapter->query($sqlAlter);
- ]]></programlisting>
- <para>
- Voici une méthode simple pour générer une chaîne aléatoire pour chaque
- utilisateur à leur enregistrement :
- </para>
- <programlisting language="php"><![CDATA[
- for ($i = 0; $i < 50; $i++)
- {
- $dynamicSalt .= chr(rand(33, 126));
- }
- ]]></programlisting>
- <para>Et maintenant, construisons l'adaptateur :</para>
- <programlisting language="php"><![CDATA[
- $adapter = new Zend_Auth_Adapter_DbTable(
- $db,
- 'users',
- 'username',
- 'password',
- "MD5(CONCAT('"
- . Zend_Registry::get('staticSalt')
- . "', ?, password_salt))"
- );
- ]]></programlisting>
- <note>
- <para>
- Vous pouvez encore améliorer la sécurité en utilisant une chaîne de "salt"
- statique codée en dur dans votre application. Dans le cas ou la base de données est
- compromise (par exemple par une attaque de type injection <acronym>SQL</acronym>)
- mais que votre serveur Web est intact, les données sont inutilisables par
- l'attaquant.
- </para>
- </note>
- <para>
- Une autre alternative est d'utiliser la méthode <methodname>getDbSelect()</methodname>
- de la classe <classname>Zend_Auth_Adapter_DbTable</classname> après la construction de
- l'adaptateur. Cette méthode retournera une instance d'objet
- <classname>Zend_Db_Select</classname> utilisée pour réaliser la routine
- <methodname>authenticate()</methodname>. Il est important de noter que cette méthode
- retournera toujours le même objet, que la méthode
- <methodname>authenticate()</methodname> a été appelée ou non. Cet objet
- <emphasis>ne comportera aucune</emphasis> information d'identité ou de crédit puisque
- celles-ci sont placées dans l'objet select au moment de
- <methodname>authenticate()</methodname>.
- </para>
- <para>
- Un exemple de situation nécessitant l'utilisation de la méthode
- <methodname>getDbSelect()</methodname> serait de vérifier le statut d'un utilisateur,
- en d'autres termes pour voir si le compte d'un utilisateur est activé.
- </para>
- <programlisting language="php"><![CDATA[
- // En continuant avec l'exemple ci-dessus
- $adapter = new Zend_Auth_Adapter_DbTable(
- $db,
- 'users',
- 'username',
- 'password',
- 'MD5(?)'
- );
- // Récupérer l'objet select (par référence)
- $select = $adapter->getDbSelect();
- $select->where('active = "TRUE"');
- // Authentification, ceci s'assure que users.active = TRUE
- $adapter->authenticate();
- ]]></programlisting>
- </sect2>
- </sect1>
|