Sunteți pe pagina 1din 54

1

5/2009

7/2010

Webdesign Formation

www.aditik.com

Rfrencement

Table des matires

Expertise Joomla
Formation tous niveaux Cration / adaptation de templates Ralisation et maintenance de sites

Organisme de formation agr

Intgration de sites E-commerce


Magento Prestashop Virtuemart

Parmi nos rfrences


www.rungis-fleurs.com www.allintubes.com www.vinespagnol.fr www.rungis-boutiques.com www.nbmglobalknowledge.com www.wecontrol.ch www.surveycopter.fr

Formation - Audit - Conseil - Ralisation - Webmastering


Des professionnels vous transmettent leur savoir-faire
www.phpsolmag.org
3

8/2010

Le priodique phpsolutions est publi par Software Press Sp. z o.o. SK Bokserska 1, 02-682 Varsovie, Pologne Tl. 0975180358, Fax. +48 22 244 24 59 www.phpsolmag.org Prsident de Software Press Sp. z o.o. SK : Pawe Marciniak Directrice de la publication : Ewa ozowicka Dpt lgal : parution ISSN : 1731-4593 Rdacteur en chef : ukasz Bartoszewicz Couverture : Sawomir Sobczyk DTP : Sawomir Sobczyk Studio2W@gmail.com Composition : Sawomir Sobczyk Correction : Valrie Viel, Thierry Borel, Barbara Bourdelles Bta-testeurs : Fabrice Gyre, Brice Favre, Valrie Viel, Cyril David, Christophe Milhau, Alain Ribault, Stphane Guedon, Eric Boulet, Mickael Puyfages, Christian Hernoux, Isabelle Lupi, Antoine Beluze, Timote Neullas, Yann Faure, Adrien Mogenet, Jean-Franois Montgaillard, Turmeau Nicolas, Jonathan Marois, Wilfried Ceron, Wajih Letaief, Franois Van de Weerdt, Eric Vincent, Franck Michal Assi, Francis Hulin-Hubard. Les personnes intresses par la coopration sont pries de nous contacter : editor@phpsolmag.org Publicit : publicite@software.com.pl Pour crer les diagrammes on a utilis le programme

TABLE DES MATIRES VARIA


6 Actualits
Actualits du monde du dveloppement. Christophe Villeneuve

PROJETS

8 Cration dun composant MVC Joomla!

Dony Chiquel Un composant se dfinit comme une application intgre qui sert tendre les fonctionnalits dun systme. Bien que certains composants tels que newsfeeds, banners, contact soient inclus lors de linstallation, Joomla! offre aux dveloppeurs la possibilit de crer des composants personnaliss et adapts leurs besoins. Dans cet article lauteur vous explique tape par tape comment sy prendre pour crer et intgrer un composant Joomla! 1.6 Beta, respectant le modle MVC.

DOSSIER

23 Scurit des sessions PHP

Ccile Odero, Magali Contensin Les sessions reposent sur un jeton unique pour reconnatre lutilisateur au cours de sa navigation. Ceci expose les applications des attaques o le pirate usurpe lidentit dun utilisateur lgitime afin daccder au systme dinformation. Grce cet article vous apprendrez scuriser les sessions.

33 Scurisation dun rpertoire avec .htaccess et .htpasswd

Franck Canonne Sur un site internet ou plus encore sur une webapp, il est souvent utile de scuriser un dossier pour en limiter laccs aux seuls utilisateurs autoriss. Apache fournit pour cela une solution trs efficace : la protection par fichier .htaccess et .htpasswd.

AVERTISSEMENT Les techniques prsentes dans les articles ne peuvent tre utilises quau sein des rseaux internes. La rdaction du magazine nest pas responsable de lutilisation incorrecte des techniques prsentes. Lutilisation des techniques prsentes peut provoquer la perte des donnes !

8/2010

Table des matires

PRATIQUE
36 Communication Flash/PHP
Jrme Manchon Flash, PHP, est-il encore bien ncessaire de les prsenter ? Si largement rpandus que chaque internaute les connat au moins de nom, leur succs na dgal que leur efficacit. Chacun sa spcialit, chacun son utilisation, runis pour crer des applications alliant lergonomie et le dynamisme. Dcouvrez comment faire communiquer une application flash AS2 et un script PHP.

requtes HTTP distinctes des informations propres lutilisateur courant. La configuration par dfaut de PHP stocke les donnes sur le serveur dans des fichiers textes. Dans certaines situations, ce moyen de stockage des sessions nest pas le plus appropri et peut se voir remplacer par un moteur de stockage diffrent, une base de donnes par exemple.

POUR LES DBUTANTS


50 Les applications WEB 2.0
Nicolas Turmeau Le web regorge de sites quon nomme parfois applications Web 2.0. Au travers de son histoire, le web avolu pour aboutir limage quon connat de lui aujourdhui. Dans cet article nous verrons dans un premier temps ce quest le Web 2.0 puis nous illustrerons cette notion au travers de diffrentes applications.

FICHE TECHNIQUE

40 Usages avancs des sessions avec la POO


Hugo Hamon Aujourdhui, la grande majorit des sites dynamiques crits en PHP utilisent le mcanisme natif des sessions. Cet outil permet de faire persister entre deux

Actualits

PHP Compta 5.2

PHP Compta est un logiciel distribut sous licence Open Source et destin aux indpendants, les associations et les PME. Il est compatible avec la gestion comptable franaise et belge. Il va vous permettre de tenir les journaux comptable, de banque, une balance et rapprocher les critures. http://www.phpcompta.be/

NuCaptcha

Dolibarr 2.9

La nouvelle version de Dolibarr vient de sortir. Cette nouvelle version apporte de nombreuses fonctionnalits (document ODT, ltres, tableau de Gantt, TVA...) et propose de nombreuses amliorations (comme les frais de dplacements). Par ailleurs, ce logiciel ERP/CRM est plus rapide grce une amlioration du moteur. http://www.dolibarr.fr

Tine 2.0

Il sagit dune plateforme collaborative associ un CRM. Il va vous permettre de regrouper et de rassembler les informations importantes sur un mme espace. Vous aurez disposition un carnet dadresses, une gestion de tables, un suivi de dossier, des exportations PDF, une version pour support mobile et une gestion administrative de la VOIP. Lensemble de loutil a t dvelopp pour vous en faciliter lutilisation. http://www.tine20.org/

NuCaptcha rejoint la famille des applications anti-spam mais il est compltement diffrent des captchas classiques. Ce nouveau projet a t lanc sur lide que les captchas deviennent de plus en plus complexes pour limiter le dchiffrage du code par les robots, et surtout plus ou moins lisibles pour un il humain. NuCaptcha se prsente sous la forme dune animation vido au format Flash, comme ceci lors de laffichage de celui-ci dans un formulaire, vous tes certain que la saisie effectue est bien celle dune personne et quil ne sagit pas dun robot. Laffichage de lanimation se compose dune image de fond et dun texte en 2 couleurs, que vous aurez la possibilit de choisir parmi la liste propose par le service du site. La partie de validation concerne une partie du texte, reprsente par des caractres rouges. Grce un affichage anim, le texte est compltement lisible par un il, mais pas du tout par un robot. Bien sr, pour insrer ce captcha dans votre formulaire, lopration seffectue par lintermdiaire dune librairie et du langage PHP. Il se place nimporte o dans votre formulaire puisquune seule partie du texte est saisir. http://www.nucaptcha.com/

Forum PHP 2010

TokuDB 4.1

Il sagit dun moteur de stockage MySQL, qui va vous permettre damliorer les performances des bases de donnes volumineuses, en acclrant lindexation par 10 50. Vous trouverez une interface simpli e, une amlioration de la rapidit et une rponse parfaite aux transactions ACID. http://tokutek.com/products/tokudb-formysql-v4/

Zend Framework 1.10.8

La nouvelle version de Zend Framework vient de sortir. Il sagit dune version mineure mais il est important deffectuer la migration car elle comporte de nombreux correctifs importants mais aussi introduit les dernires modi cations didenti cation de Twitter. http://devzone.zend.com/

MediaWiki 1.16.0

MediaWiki est un moteur de wiki pour le Web et vient de publier une nouvelle version avec de nombreuses nouveauts : les ux au format Atom, de nouvelles options (maintenance, prfrences), acclrations avec la base de donnes. Par ailleurs, il est possible de bloquer lenvoi demails par les utilisateurs et le systme de gestion ACL a volu. http://techblog.wikimedia.org/

LAFUP (Association Franaise des Utilisateurs de PHP) vient de dvoiler le programme du forum PHP 2010. Le forum PHP va se drouler le 9 et 10 novembre prochain la cit des sciences et de lindustrie Paris pour la deuxime anne conscutive. Cette anne nest pas une anne comme les autres car il sagit dun double anniversaire avec les 15 ans de PHP et les 10 ans de lassociation. Et pour marquer lvnement, de nombreux points vont vous faire venir ce double anniversaire. Tout dabord, la prsence du crateur de PHP : Rasmus Lerdoff, qui viendra nous parler de son langage favori : Le PHP. Ensuite, le contenu du programme est trs diversifi autour du thme PHP comprenant de nombreux points qui vont vous intresser comme : La dcouverte autour de PHP (Prsentation, veille technologie, GIT / SVN). Architecture et Dveloppement (Industrialisation, dveloppement, base de donnes). Framework. Infrastructure (Hbergement, performance, scurit). Qualit / Efcacit individuelle et collective. Applications mtier : CMS et e-commerce. Le Web. La totalit du programme, des confrences sont disponibles sur le site du Forum. Par ailleurs, vous trouverez toutes les informations pour rserver votre place : http://www.afup.org/forumphp. Rdaction des actualits : Christophe Villeneuve

8/2010

<<TOP>>
<<SHORT_NEWS>>

<<BODY>>

www.phpsolmag.org

Projets

Cration

dun composant MVC Joomla!


Un composant se dfinit comme une application intgre qui sert tendre les fonctionnalits dun systme. Bien que certains composants tels que newsfeeds, banners, contact soient inclus lors de linstallation, Joomla! offre aux dveloppeurs la possibilit de crer des composants personnaliss et adapts ses besoins.
Cet article explique :
Cet article explique tape par tape comment sy prendre pour crer et intgrer un composant Joomla! 1.6 Beta, respectant le modle MVC.

Ce quil faut savoir :


Connaissances du langage SQL. Bonne matrise du PHP et du HTML. Connaissance de Joomla!.

e modle MVC est une mthode de conception base sur une architecture qui permet la sparation de lapplication en trois couches : modle, vue et contrleur (voir Figure 1). Le modle correspond aux donnes de lapplication; il assure le traitement des donnes. La vue se charge dafcher les donnes envoyes par le modle et de recevoir les actions de lutilisateur (clic de souris, slection dune entre, boutons, etc). Le contrleur gre linteraction et la synchronisation entre le modle et la vue.

Les composants Joomla!

Les composants se rpartissent en deux catgories : Les composants Frontend : ceux-ci constituent la partie publique cest dire visible par les visiteurs.

Interaction entre les trois couches

Le contrleur se charge de prendre en charge les vnements de lutilisateur puis dclenche les actions pour synchroniser la vue et/ou le modle. Si une action exige un changement des donnes, le contrleur demande au modle la modification des donnes ; le modle avertit la vue que les donnes ont chang pour quelle se mette jour. Certains vnements de lutilisateur ne concernent pas les donnes mais la vue. Dans ce cas, le contrleur demande la vue de se modifier. Le contrleur neffectue aucun traitement, ne modifie aucune donne. Il analyse la requte du client et se contente dappeler le modle adquat et de renvoyer la vue correspondant la demande (voir Figure 2).

Figure 1. Modle MVC 8/2010

MVC Joomla!

Figure 2. Diagramme de squence dun modle MVC

Les composants Backend : ils ne sont accessibles que par ladministrateur et servent ladministration du site. Il est possible de reconnatre les composants partir de lcriture de ladresse URL : Le lien http://localhost/votre-site-Joomla/index. php?option=com_newsfeeds fait appel au composant Frontend com_newsfeeds. Le modle MVC Joomla! est implment en utilisant trois classes fournies par le Framework Joomla! : Jmodel, Jview et Jcontroller.

/components/com_produit/frontend/views/produits/ tmpl/default.php ; /components/com_produit/frontend/models/produit. php.

Le point dentre : /frontend/produit.php

Cest le point dentre du composant, il doit obligatoirement porter le mme nom que celui-ci. Ce fichier dlgue les oprations effectues par notre composant. Cest lui qui est excut en premier lorsquon entre ladresse URL suivante : http://localhost/votre-site-joomla/index.php?option=com_produits&view=produit. Examinons le contenu de ce fichier (voir Listing 1). Linstruction defined( '_JEXEC' ) or die( 'Accs restreint' ); vrifie si la demande dexcution de ce fichier a t lance par Joomla !. Si ce nest pas le cas, la fonction die( 'Accs restreint' ) interrompt automatiquement la demande. La ligne require_once( JPATH_COMPONENT. DS.'controller.php' ); dsigne le chemin absolu notre composant. Les variable JPATH_COMPONENT_SITE ou JPATH_COMPONENT_ADMINISTRATOR peuvent tre utilises si lon veut accder des composants Frontend ou Backend. Le suffixe DS symbolise le sparateur de rpertoire du systme dexploitation utilis : / pour Windows et \ pour Unix. Ceci vite au dveloppeur de crer des versions diffrentes pour chaque systme dexploitation.
9

Problmatique

Nous voulons crer un module permettant de grer des produits ; ladministrateur doit pouvoir ajouter, supprimer et modifier les produits et les utilisateurs auront la possibilit de consulter la liste des produits sans pouvoir les modifier. Nous allons donc concevoir un Frontend et un Backend.

Le Frontend

Comme il a t dit prcdemment, le front est la partie visible aux visiteurs. Il est compos de plusieurs fichiers : /components/com_produit/frontend/produit.php ; /components/com_produit/frontend/controller.php ; /components/com_produit/frontend/views/produits/ view.html.php ;

www.phpsolmag.org

Projets

Listing 1. Code source du chier /frontend/produit.php


<?php // Accs direct interdit de ned(' _ JEXEC') or die('Accs restreint'); // Chargement du contrleur primaire de Joomla! require _ once (JPATH _ COMPONENT.DS.'controller.php'); // Cration d'un contrleur spcique $controller = new ProduitController(); // Lecture de la tche raliser $controller->execute(JRequest::getCmd('task')); // Redirection vers le contrleur $controller->redirect(); ?>

JRequest::getCmd( 'task' ) sert vrifier si lURL saisie contient des paramtres. Ces paramtres peuvent correspondre une demande daffichage, un ajout, une modification ou une suppression. $controller->redirect(); permet de faire une redirection, gnralement aprs une modification (ajout, suppression, changement de valeur).

Cration du Contrleur : /frontend/controller.php

Listing 2. Code source du chier /frontend/controller.php


<?php // Pas d'accs direct de ned( ' _ JEXEC' ) or die( 'Accs restreint' ); //importation de la classe JController jimport('joomla.application.component.controller'); class ProduitController extends JController { // afchage function display() { parent::display(); } }

Le contrleur est le composant principal de larchitecture MVC. Il interagit avec le modle, la vue ainsi quavec dautres contrleurs. Le contrleur capte et analyse les requtes de lutilisateur ; il accde ensuite au modle pour enfin prsenter la vue. Examinons le Listing 2 pour analyser le code du contrleur. La fonction display() est la fonction par dfaut excute par le constructeur de la classe Jcontroller si aucune autre tche nest demande. Cette fonction ne fait rien dautre quappeler la fonction display() de la classe parente.

Cration de la vue : /frontend/views/produits/view.html.php

Listing 3. Code source du chier /frontend/produits/view. html.php


<?php // Pas d'accs direct de ned( ' _ JEXEC' ) or die( 'Accs restreint' ); //importation de la classe JView jimport( 'joomla.application.component.view'); class ProduitViewProduit extends JView{ //fonction afchage function display($tpl = null){ //cration d'une instance du modle $model = &$this->getModel(); //gnration d'une liste des produits $rows = $model->getProduitList(); $this->assignRef('rows' , $rows); parent::display($tpl); } } ?>

La vue neffectue aucun traitement ; sa tche se rsume recevoir les actions de lutilisateur et dafficher les rsultats renvoys par le modle. Les rsultats dun mme modle peuvent tre affichs par plusieurs vues distinctes. Voyons un exemple de vue (Listing 3). Linstruction $model = &$this->getModel(); nous a permis de crer une instance du modle nomme $model ; la mthode getProduitList() ($rows $model->getProduitList();) quant elle, renvoie un tableau ($rows) qui contient les enregistrements des produits. Ce rsultat est ensuite transmis au template que nous allons voir dans le paragraphe suivant.

Cration du template : /frontend/views/produits/tmpl/default.php

Listing 4. Code source du chier /frontend/produits/tmpl/ default.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); ?> <h1><?php echo "Liste des produits"; ?></h1> <ul> <?php // Lecture des enregistrements vers un tableau foreach ($this->rows as $row) { ?> <li><?php echo $row->designation; ?></li> <li><?php echo $row->description; ?></li> <?php } ?> </ul>

Les templates sont des fichiers utiliss pour lagencement des donnes en provenance de la vue. Nous allons construire un template simple contenant du code html, php (Listing 4). tant donn que la mise en forme est maintenant grable de manire autonome depuis Joomla! 1.5, la prsentation des templates peut tre enrichie en utilisant des outils et des diteurs appropris comme Dreamweaver, MooTools.

Cration du modle : frontend/models/produit.php

Le modle encapsule laccs la source de donnes. Il est totalement indpendant du reste; il ne connat ni les contrleurs, ni les vues car les liens vont des contrleurs vers le modle et parfois des vues vers le modle mais jamais linverse. Jetons un coup dil sur le Listing 5 pour voir le contenu de ce fichier.
8/2010

10

MVC Joomla!

Cest la mthode _getProduitQuery() qui est charge daccder aux donnes et cest aussi elle qui contient la requte SQL. La mthode getProduitList se charge de contrler laccs et rcuprer le rsultat. Ce qui nous renvoie la ligne $rows = $model->getProduitList(); du code du fichier views.html.php (Listing 3 ).

Listing 5. Code source du chier /frontend/models/produit. php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); //Importation du modle JModel jimport('joomla.application.component.model'); class ProduitModelProduit extends JModel { //Prparation de la requte (slection des produits publis) function _ getProduitQuery( &$options ) { $db JFactory::getDBO(); $id @$options['id']; = =

Le Backend

Cette partie est rserve ladministrateur du site ; cest ici que soprent lajout, la suppression, la modification et la publication des enregistrements. Plusieurs fichiers sont utiliss dans cette partie. En voici la liste : /components/com_produit/backend/admin.produit. php ; /components/com_produit/backend/controller.php; /components/com_produit/backend/controllers/produit.php; /components/com_produit/backend/views/produits/ view.html.php ; /components/com_produit/backend/views/produits/ tmpl/default.php ; /components/com_produit/backend/views/produit/ view.html.php ; /components/com_produit/backend/views/produit/ tmpl/form.php ; /components/com_produit/backend/tables/produit. php ; /components/com_produit/backend/install.sql ; /components/com_produit/backend/uninstall.sql.

$select = 'p.*'; $from = '# _ _ produit AS p'; $wheres[] = 'p.publication = 1'; $query = "SELECT " . $select . "\n FROM " . $from AND ", $wheres ); "\n WHERE " .

. implode( "\n

publis)

return $query; } //Afchage des rsultats (liste des produits

Le point dentre : backend/admin.produit.php

function getProduitList( $options=array() ) { $query = $this-> _ getProduitQuery( $options ); $result = $this-> _ getList( $query ); return @$result; } } ?>

Tout comme pour le frontend, il faut galement crer un point dentre pour le backend. La seule diffrence entre ces deux points dentre est que celui du backend possde une condition qui vrifie sil y a des contrleurs spcifiques aprs le contrleur de base. Examinons le contenu de ce fichier (Listing 6).

Listing 6. Code source du chier backend/admin.produit.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); //Importation du contrleur de base require _ once (JPATH _ COMPONENT.DS.'controller.php'); // Importation contrleur spcique ()sur demande) if($controller = JRequest::getVar('controller')) { require _ once (JPATH _ COMPONENT. DS.'controllers'.DS.$controller.'.php'); } // Cration du contrleur $classname = 'ProduitsController'.$controller; $controller = new $classname( ); // Excution de la tche demande $controller->execute(JRequest::getCmd('task')); // Redirection $controller->redirect(); ?>

Le contrleur primaire: backend/controller.php

Le code contrleur primaire du backend est identique celui du frontend. Nous allons donc faire une copie du contrleur du frontend (Listing 2) tant donn quaucune modification nintervient ce niveau.

Contrleur supplmentaire : backend/controllers/produit.php

Ce contrleur contient plusieurs mthodes : diter, sauvegarder, supprimer, publier et annuler. Chacune de ces mthodes instancie le modle travers linstruction $model = $this->getModel('produit'); . Les classes JText et JError interagissent avec lutilisateur pour le renseigner sur le droulement des oprations (Listing 7).
www.phpsolmag.org

11

Projets

Listing 7. Code source du chier backend/controllers/produit. php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); class ProduitsControllerProduit extends ProduitsController { //Constructeur function _ _ construct() { parent:: _ _ construct(); // Recensement des tches $this->registerTask( 'add' ,

'task' ); );

$task

= JRequest::getCmd(

$publish = ($task == 'publish'); $n = count( $cid

if (empty( $cid )) { return JError::raiseWarning( 500, JText:: _ ( 'Aucun produit slctionn' ) ); } JArrayHelper::toInteger( $cid ); $cids = implode( ',', $cid ); $query = 'UPDATE # _ _ produit' . ' SET published = ' . (int) $publish . ' WHERE id IN ( '. $cids .' )' ; $db->setQuery( $query ); if (!$db->query()) { return JError::raiseWarning( 500, $row->getError() ); } $this->setMessage( JText::sprintf( $publish ? 'Produit publi' : 'Produit non publi', $n ) ); } //Annulation function cancel() { $msg = JText:: _ ( 'Operation annule'

'edit' ); 'publish'); }

$this->registerTask( 'unpublish',

//Afchage du formulaire d'dition function edit() { JRequest::setVar( 'view', 'produit' ); JRequest::setVar( 'layout', 'form' ); JRequest::setVar('hidemainmenu', 1); } parent::display();

);

//Enregistrement function save() { $model = $this->getModel('produit'); if ($model->store($post)) { $msg = JText:: _ ( 'Produit } else {

$this->setRedirect( 'index. php?option=com _ produits', $msg ); } } ?>

enregistr!' );

$msg = JText:: _ ( 'Erreur lors de l enregistrement du produit' ); } produits'; } $link = 'index.php?option=com _ $this->setRedirect($link, $msg);

Listing 8. Code source du chier backend/views/produits/view. html.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); //Importation de la vue JView jimport( 'joomla.application.component.view' ); class ProduitsViewProduits extends JView { //Afchage des boutons standards de Joomla! function display($tpl = null) { JToolBarHelper::title( JText:: _ ( 'Gestionnaire des produits' ), 'generic.png' ); JToolBarHelper::publishList(); JToolBarHelper::unpublishList(); JToolBarHelper::deleteList(); JToolBarHelper::editListX(); JToolBarHelper::addNewX(); // Rcupration des donnes en provenance du modle $items = & $this->get( 'Data'); $items); $this->assignRef('items',

//Suppression function remove() { $model = $this->getModel('produit'); if(!$model->delete()) { $msg = JText:: _ ( 'Erreur: suppression impossible' ); } else { $msg = JText:: _ ( 'Produit(s) supprim(s)' ); } $this->setRedirect( 'index. php?option=com _ produits', $msg ); } //Publications function publish() { $this->setRedirect( 'index. php?option=com _ produits' ); // Initialisation des variables $db =& JFactory:: $user =& JFactory:: = JRequest::getVar(

getDBO(); getUser();

parent::display($tpl); } }

$cid 'cid', array(), 'post', 'array' );

12

8/2010

MVC Joomla!

www.phpsolmag.org

13

Projets

Listing 9. Code source du chier backend/views/produits/tmpl/ default.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); ?> <form action="index.php" method="post" name="adminForm"> <div id="editcell"> <table class="adminlist"> <thead> <tr> <tr> <th width="5"> <?php echo JText:: _ ( 'NUM' ); ?> </th> <th width="20"> <input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count( $this->items ); ?>);" /> </th> <th class="title"> <?php echo JHTML:: _ ('grid.sort', 'Produit', 'a.description', @$lists['order _ Dir'], @$this->lists['order'] ); ?> </th> <th width="5%" align="center"> <?php echo JHTML:: _ ('grid.sort', 'Publication', 'a.publication', @$this>lists['order _ Dir'], @$this->lists['order'] ); ?> </th> <th width="1%" nowrap="nowrap"> <?php echo JHTML:: _ ('grid.sort', 'ID', 'a.id', @$this->lists['order _ Dir'], @$this->lists['order'] ); ?> </th> </tr> </thead> <?php $k = 0; for ($i=0, $n=count( $this->items ); $i < $n; { $row = &$this->items[$i];

$published;?>

<?php echo </td> <td align="center"> <?php echo $row->id; </td> </tr> <?php $k = 1 - $k;

?>

} ?> </table> </div>

<input type="hidden" name="option" value="com _ produits" /> <input type="hidden" name="task" value="" /> <input type="hidden" name="boxchecked" value="0" /> <input type="hidden" name="controller" value="produit" /> </form>

Listing 10. Code source du chier /backend/views/produit/view. html.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); //Importation de la vue JView jimport( 'joomla.application.component.view' ); class ProduitsViewProduit extends JView { //Afchage function display($tpl = null) { $produit =& $this->get('Data'); $isNew = ($produit->id < 1); $text = $isNew ? JText:: _ ( 'New' ) : JText:: _ ( 'Edit' ); JToolBarHelper::title( JText:: _ ( 'Produit' ).': <small>[ ' . $text.' ]</small>' ); JToolBarHelper::save(); // La variable isNew dtermine si le produit existe ou pas // Si le produit n'existe pas dans la BD, il sera cr if ($isNew) { JToolBarHelper::cancel(); } else { // Pour les produits existant le bouton 'cancel' sera remplac par le bouton 'close' JToolBarHelper::cancel( 'cancel', 'Close' ); } //La mthode assignRef() permet de transmettre le contenu de la variable et son nom au template. $this->assignRef('produit', $produit); parent::display($tpl); } }

$i++)

$published = JHTML:: _ ('grid.publication', $row, $i ); $checked = JHTML:: _ ('grid.id', $i, $row->id ); $link = JRoute:: _ ( 'index. php?option=com _ produits&controller=produit&task=edit&c id[]='. $row->id ); ?> <tr class="<?php echo "row$k"; ?>"> <td> <?php echo $row->id; </td> <td> </td> <td>

?>

?>

<?php echo $checked;

<a href="<?php echo $link; ?>"><?php echo $row->description; ?></a> </td> </ td> <td align="center">

14

8/2010

MVC Joomla!

Listing 11. Code source du chier /backend/views/produit/tmpl/ form.php


<?php de ned(' _ JEXEC') or die('Restricted access'); ?> <script language="javascript" type="text/javascript"> function submitbutton(pressbutton) { var form = document.adminForm; if (pressbutton == 'cancel') { submitform( pressbutton ); return; } // Validation des champs if (form.text.value == "") { alert( "<?php echo JText:: _ ( 'Ce champ doit tre renseign', true ); ?>" ); } else { submitform( pressbutton ); } } </script> <form action="index.php" method="post" name="adminForm" id="adminForm"> <div> < eldset class="adminform"> <legend><?php echo JText:: _ ( 'Details' ); ?></ legend> <table class="admintable"> <tr> <td width="110" class="key"> <label for="title"> <?php echo JText:: _ ( 'Dsignation' ); ?>: </label> </td> <td> <input class="inputbox" type="text" name="designation" id="designation" size="60" value="<?php echo $this>produit->designation; ?>" /> </td> </tr> <tr> <td width="110" class="key"> <label for="alias"> <?php echo JText:: _ ( 'Description' ); ?>: </label> </td> <td> <input class="inputbox" type="text" name="description" id="description" size="60" value="<?php echo $this>produit->description; ?>" /> </td> </tr> <tr> 'Publication' ); ?>: <td width="120" class="key"> <?php echo JText:: _ ( </td> <td>

</table> </eldset> </div> <div class="clr"></div> <div class="clr"></div> <input type="hidden" name="option" value="com _ produits" /> <input type="hidden" name="id" value="<?php echo $this>produit->id; ?>" /> <input type="hidden" name="task" value="" /> <input type="hidden" name="controller" value="produit" /> </form>

Listing 12. Code source du chier /backend/tables/produit.php


<?php // Contrle pour s'assurer que le chier //est inclus dans Joomla! de ned(' _ JEXEC') or die('Accs restreint'); class TableProduit extends JTable { //Initialisation des variables /** @var int Primary key */ var $id /** @var string */ var $description /** @var string */ var $designation /** @var string */ var $publication /** @var int */

= 0; = ''; = ''; = 0;

// Mapping objet relationnel function TableProduit(& $db) { parent:: _ _ construct('# _ _ produit', 'id', $db); } } ?>

Listing 13. Code source du chier backend/install.sql


DROP TABLE IF EXISTS '# _ _ produit'; CREATE TABLE '# _ _ produit' ( 'id' int(11) NOT NULL auto _ increment, 'description' text, 'designation' varchar(100) NOT NULL, 'publication' tinyint(1) NOT NULL, PRIMARY KEY ('id') ); INSERT INTO # _ _ produit VALUES (2, 'Telephone', 'SmartPhone', 1); INSERT INTO # _ _ produit VALUES (4, 'Ordinateur', 'MacBook', 1);

<?php echo JHTML:: _ ( 'select.booleanlist', 'publication', 'class="inputbox"', $this->produit->publication ); ?> </td> </tr>

Listing 14. Code source du chier backend/uninstall.sql


DROP TABLE IF EXISTS '# _ _ produit';

La vue : backend/views/produits/view.html.php

Cette vue concerne la barre doutils administrative ; elle fait intervenir la classe JtoolBarHelper charge dafficher les contrles administratifs tels que : publier, dpublier, diter, supprimer, nouveau. Analysons le code source de ce fichier (Listing 8).
www.phpsolmag.org

Le template : backend/views/produits/tmpl/ default.php

Ce template se charge de la mise en forme de laffichage de la liste de nos produits ; il contient du code html, php et Javascript (Listing 9).
15

Projets

Listing 15. Code source du chier /backend/produit.xml


<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/component-install.dtd"> <install type="component" version="1.5.0"> <!-- Informations sur le composant --> <name>Gestionnaire de Produits</name> <creationDate>16/08/2010</creationDate> <author>Admin</author> <authorEmail>admin@admin.com</authorEmail> <authorUrl>www.admin.com</authorUrl> <copyright>Copyright</copyright> <license>Open source</license> <version>1.0.0</version> <description>Composant de gestion des produits</description> <!-- Structure des dossiers et des chiers de la partie frontend--> < les folder="frontend"> < lename>index.html</ lename> < lename>produit.php</ lename> < lename>controller.php</ lename> < lename>views/index.html</ lename> < lename>views/produit/index.html</ lename> < lename>views/produit/view.html.php</ lename> < lename>views/produit/tmpl/index.html</ lename> < lename>views/produit/tmpl/default.php</ lename> < lename>models/produit.php</ lename> </ les> <!-- Informations sur la cration de la table du composant lors de l'installation--> <install> <sql> < le charset="utf8" driver="mysql">install.sql</ le> </sql> </install> <!-- Informations sur la supprssion de la table du composant lors de la dsinstallation--> <uninstall> <sql> < le charset="utf8" driver="mysql">uninstall.sql</ le> </sql> </uninstall> <!-- Structure des dossiers et des chiers de la partie frontend--> <administration> <menu>Produit</menu> < les folder="backend"> < lename>index.html</ lename> < lename>admin.produit.php</ lename> < lename>controller.php</ lename> < lename>controllers/produit.php</ lename> < lename>controllers/index.html</ lename> < lename>models/produit.php</ lename> < lename>models/produits.php</ lename> < lename>models/index.html</ lename> < lename>views/produits/view.html.php</ lename> < lename>views/produits/index.html</ lename> < lename>views/produits/tmpl/default.php</ lename> < lename>views/produits/tmpl/index.html</ lename> < lename>views/produit/view.html.php</ lename> < lename>views/produit/tmpl/form.php</ lename> < lename>views/produit/index.html</ lename> < lename>views/produit/tmpl/index.html</ lename> < lename>tables/produit.php</ lename> < lename>tables/index.html</ lename> < lename>install.sql</ lename> < lename>uninstall.sql</ lename> </ les> </administration> </install>

La vue formulaire : /backend/views/produit/view.html.php

Celle-ci concerne laffichage de la fiche dun produit ; nous allons galement construire une barre doutils pour cette vue afin de donner la possibilit ladministrateur de pouvoir modifier le produit slectionn (Listing 10).
16

Le formulaire du template : /backend/views/produit/tmpl/ form.php

Ce formulaire permet de modifier le produit affich par la vue /backend/produit/view.html.php. Consultons le contenu de son code source (Listing 11).
8/2010

MVC Joomla!

Figure 3. Structure du paquetage nal

Figure 4. Installation russie

Figure 5. Composant produit

La classe produit : /backend/tables/produit.php

Cette classe indique au modle les donnes quil doit manipuler. Elle implmente linterface JTable qui lui confre la simplicit daccder aux donnes et dutiliser ses mthodes. Le nom de la table ainsi que la cl primaire sont fixs dans le constructeur de la classe (Listing 12).
www.phpsolmag.org

Le fichier dinstallation : backend/install.sql

Ce fichier contient des instructions SQL afin de donner Joomla! les informations ncessaires la cration de la table du composant au moment de linstallation (Listing 13).

17

Projets

Figure 6. Menu composant

Le fichier de dsinstallation : backend/uninstall.sql

Celui-ci intervient la dsinstallation du composant pour la suppression de la table du composant; il ne contient quune seule instruction comme nous allons le voir dans le Listing 14.

Le fichier de configuration : backend/produit.xml

ser notre dossier com_produit afin dobtenir un dossier compress : com_produit.zip qui servira linstallation. Aprs linstallation du composant , un message de confirmation du bon droulement de lopration vous sera affich (Figure 4). Vous pourrez vous rendre dans le gestionnaire des extensions pour voir si notre composant est bien prsent (Figure 5) ou jeter un coup dil dans le menu composant (Figure 6).

Cest ce fichier qui dcrit le nouveau composant ; les informations contenues dans le fichier de configuration seront utilises durant linstallation. Il doit contenir les noms et les emplacements de tous les fichiers qui constituent le composant, cest grce a que Joomla! parvient crer la table dans la base de donnes, les sous-dossiers, y placer les fichiers (Listing 15).

Environnement de developpement

Cet exemple a t ralis dans un environnement constitu de : Joomla! 1.6 Beta ; XAMPP for Linux 1.7.3a ; Ubuntu Lucid 10 LTS ; Firefox.

Paquetage dinstallation

Cest la dernire tape du travail ; nous allons assembler les diffrentes parties de notre composant au sein dun mme dossier que nous nommerons : com_produit. Notre paquetage final aura une structure identique celle prsente sur la Figure 3. Nous allons compres-

Sur Internet
http://api.joomla.org/Joomla-Framework/Application/ JController.html API Joomla!, http://extensions.joomla.org/extensions/miscellaneous/ development/1509/details Projet communautaire Joomla !, site communautaire des dveloppeurs Joomla!, http://cocoate.com/fr/node/1870/conception-de-composants-de-modules-et-de-plugins/un-exemple-completauto Un exemple sur la conception de composant, de module et de plugin.

DONY CHIQUEL
Dony Chiquel est un ingnieur dveloppeur spcialis en technologies J2EE, .NET et en conception objet avec UML. Il travaille actuellement en tant que consultant en nouvelles technologies pour le compte de BUGOVER et PROSOLUCE. 8/2010

18

Projets

BYOOS solutions

partenaire du dveloppement DURABLE !


Le logiciel OPEN SOURCE DJAFOREST au service de la protection de lenvironnement.

HISTORIQUE

DJAFOREST est un applicatif WEB de travail collaboratif qui vise montrer les mfaits de la surconsommation du papier lheure o lcologie et la protection de lenvironnement sont des faits marquants de notre socit moderne. Au sein du groupe de dveloppement nous avons dcid doffrir une application PHP qui, tout en tant oriente dveloppeur sera simple mettre en uvre et fera la promotion de la fort quatoriale du DJA situe au sud du Cameroun, Afrique Central. Cet article aussi modeste soit-il doit montrer les possibilits quoffre le langage PHP dans les projets de dveloppement RAD (Rapid Application Development) dveloppement rapide dapplication en ouvrant le choix des librairies aux applicatifs cods en PHP ayant fait leurs preuves. Les tudes ont commenc en Fvrier 2010 puis aprs avoir collect et test moult librairies, notre dveloppement a dbut fin juin 2010. Le projet sera disponible dbut Septembre 2010 afin que chaque codeur PHP intress puisse intgrer le projet en le dotant de tous les outils ncessaires sa publication en version 1.0. Par exemple : blog, forum, download, e-commerce, GED, agenda, facturation, fichier clients

www-root system application modules chaque module ou application est dcoup en fonction : cong controlers errors helpers hooks language libraries models views ce qui permet une lecture claire des scripts de contrle puis de retrouver simplement les variables daffichage au niveau des vues (./views/). Cet article nest pas un cours sur la mise en uvre de CI mais vous montre la clart du modle MVC qui facilitera dautant la maintenance des applications, pour plus dinformations allez visiter le trs bon site de CI France ladresse http://www.codeigniter.fr. Le projet DJAFOREST est encore au stade de la version bta mais dj utilisable avec son installateur automatique venu de PyroCMS et permet de coder un site WEB multi-pages, multi-news. Le Back Office SiteManagr est dot de lditeur Javascript Ckeditor ce qui offre une grande souplesse dans la composition des pages et articles. Les lments complmentaires comme les images, plugins et upload Photos sont localiss dans le rpertoire /assets/.

Le choix de codeigniter et la P.O.O (Programmation Oriente Objet)

CODEIGNITER (CI en abrg) ou le chemin du futur Je me permets cette affirmation car aprs plusieurs mois passs en veille technologique la recherche dun FrameWork PHP pour nos projets BYOOS solutions, je suis arriv au triste constat quil ny avait pas sur le march un applicatif qui rpondait nos critres. Nous avons t sduis par la simplicit de mise en uvre de CI, la possibilit de coder en PHP4 et/ou PHP5 puis par la puissance de ses librairies, sa riche documentation et depuis peu ses ressources en Franais. Le modle conceptuel de CI est conforme lapplication MVC (Models, Views, Controlers), la racine de votre projet peut comporter minima 3 rpertoires et tre pleinement fonctionnelle.
www.phpsolmag.org

LA FEUILLE DE ROUTE de DjaForest par NDI TANYU Jones stagiaire byoos.fr

Le projet de DjaForest est une application informatique de type Web cibl montrant au public le riche hritage naturel de la rserve de la fort du Dja dans la rgion du sud de la Rpublique du Cameroun en particulier, des forts quatoriales en gnral et galement dautre part
19

DJAFOREST

dcourager la population globale abattre les arbres de nos forts. On avait pens que larrive de lordinateur rduirait considrablement la quantit de copies papiers reproduites par document. Linverse sest cependant avr tre vrai, autant de documents journaliers sont imprims. Limpression signifie que lusage des papiers et de leur production est remerci grce labattage des arbres. Quand un arbre est coup, il va vers le bas avec les autres et dans certains cas lcosystme est considrablement affect. Ceci cre parfois les effets ngatifs qui vont jusqu affecter la vie de lhabitant des zones de fort comme les gens de Baka. Ceci et les activits semblables ne peuvent plus continuer en tant que tel sans tre contrles et sont bases sur le proto djaforest qui a t conu, dans son propre chemin de manire sensibiliser le public sur les dangers du dboisement.

possible. La largeur des pages considrer doit tre moindre que celle de lcran de lordinateur. Parler sur la faon dont ceci sera ralis est galement trs important. Premirement les langages de programmation employer sont : PHP (script du ct serveur) . HTML, CSS (codage du Front Ofce ou du ct client) . Javascript (codage dynamique de ct client).

Il est galement intressant de mentionner les logiciels employer qui sont : Pour Windows (c) notepad++ wamp server navigateurs Web (Firefox, opera, Google chrome, Netscape et Explorer) photoshop (pour le traitement des images) boutons libres Pour Linux ubuntu 10.04 geany diteur apache2 rapidSVN Gimp Avec ces ressources, les codes sont dactylographis en utilisant les diteurs de texte notepad++ ou Geany LINUX et excut sur les serveurs WAMPserver ou Apache 2 en utilisant les navigateurs ( FireFox, Opera, Chrome, IE ) ceci permet une meilleure apprciation de la prsentation de lapplication sur le Web. Auteur Gabriel BOBARD I.T Manager BYOOS solutions contact@byoos.fr http://www.djaforest.com http://www.byoos.fr +237 22 06 58 13 ( Cameroun ) +33 645 25 48 13 ( France )

DFINITION DES BESOINS

DjaForest est une application Web et par consquent en la mettant en place, son utilisation ne sera seulement rendue possible que si les conditions suivantes sont remplies : ordinateurs (PC pour les utilisateurs et un serveur pour accueillir lapplication) et une connexion Internet ou Intranet

MISE EN APPLICATION

Un certain nombre de ressources sont ncessaires pour lexcution de DjaForest. Les logiciels CodeIgniter, Matchbox, Sitemanagr et PyroCMS installer frameworks servent de base au codage venir. Le framework sitemanagr est employ pour la zone dadministration et Pyrocms installer permet linstallation du systme ; CodeIgniter permet de crer des thmes daffichage puis Matchbox appliqu la gestion modulaire. Mr. Gabriel Bobard Directeur de BYOOS Solutions a mis le CMS en place par intgration du framework CodeIgniter permettant tout dveloppeur Web davoir une plate-forme ou une base de travail sur laquelle il peut coder. Ce CMS offrira une page, un menu et une gestion de modules. Il a galement t prpar pour assurer une excellente rcriture URL (url rewriting). Pour la gestion de modules Matchbox, cela signifie que beaucoup dautres applications peuvent tre dveloppes et ajoutes au mme systme (galerie images, Facturation Invoice, module de e-commerce ). Le Back Office sera charg de la gestion de ladministration et linstallation du programme. Il est prvu dans la partie de Ndi Jones, tudiant de linternat de Byoos de construire le Front Office avant et de dvelopper des modules (par exemple blog et forums ...) pour lapplication. La conception du Front Office est base sur le modle du Web 2.0. Ceci signifie que les boutons seront au format du Web 2.0, le choix de couleurs pour le thme ou du modle est rduit aux quelques couleurs de base. Couleurs ptantes fortes viter autant que
20

ANNEXE 1

application dja forest 08/02/2010 version 0.1.0 Objectifs Fournir une application informatique NTIC visant rduire la consommation de papier et par l mme limiter la coupe de FORTS. Permettre au Directeur Informatique (D.S.I) de dotter les services Administratifs ou Oprationnels dun couteau SUISSE virtuel. 1) framework 2) le back ofce 3) la gestion des modules
8/2010

Projets

4) la gestion des templates 5) le front ofce Dveloppeur(s) KOUAMOU Franck Ndi TANYU Jones BOBARD Gabriel Gestion du projet BOBARD Doris Traducteur(s) MANCEAU Jacques Promoteur BYOOS solutions contact@byoos.fr Ressources
Codeigniter 1.7.2 Sitemanager 0.34 Matchbox 1.0RC2 Templates 1.4.1 CKeditor 3.1 PyroCMS http://codeigniter.fr http://designelemental.net/sitemanagr http://codeigniter.com/wiki/Matchbox/ http://williamsconcepts.com/ci/codeigniter/ libraries/template/reference.html http://ckeditor.com http://pyrocms.com

3) Toutes les ressources qui ont servi au dveloppement sont places dans le rpertoire www-root/djaforest/ressources. 10/08/2010 0.1.1b15 intgration de la librairie MATCHBOX rc2 au projet SiteManagr, intgration de linstallateur ionizecms0.94, modification de la location des bibliotques externes, javascript, flash, css, images ./assets. 16/08/2010 intgration du moteur de templates codigniter 1.7.x, supprimer les lignes de codes siteManager faisant appel aux lib de Google et rendant lapplication inutilisable hors ligne (???), lib concernes , prototype.js, scriptalous.js. 22/08/2010 version 0.1.1b23 intgration de CKeditor aux NEWS et PAGES afin de permettre une mise en page aise, intgration des liens dans la rgion sidebar. 24/08/2010 version 0.1.2b25 intgration du lecteur multimdia JW MediaPlayer, ajout de la librairie flvplayer, suppression de linstallateur de ionize-094 et remplace par linstaller de PyroCMS (nettement plus simple intgrer !!!). Formation WEBMASTER - LINUX en e-learning sur la plateforme de elearning.byoos.fr PHP5 programmation P.O.O & administration LINUX Debian - Ubuntu

http://byoos.fr

http://djaforest.com

INSTALL dcompresser larchive dans un rpertoire de votre site www-root/djaforest, placer les droits daccs aux fichiers, gnralement 644 activer le module apache mod_rewrite.c ( url rewriting ), lancer lapplication. 1) Si le logiciel DjaForest nest pas encore install sur votre machine, le programme dinstallation va alors se lancer automatiquement: www-root/djaforest/installer, entrez le nom serveur, gnralement localhost, entrez le nom de ladministrateur de la bases de donnes, entrez le mot de passe de ladministrateur de la base de donnes et VALIDER. A ce stade la cration de la base de donnes se fait de faon automatique. Ensuite entrez votre nom dutilisateur puis votre email courant et votre mot de passe VALIDEZ. entrez le nom dutilisateur admin puis le mot de passe admin. 2) Si lapplication est dj installe, le controleur principal Pages prend le contrle du code, documentation complte venir.
www.phpsolmag.org

BOBARD Gabriel Julien Pierre I.T Manager BYOOS

21

Projets

22

8/2010

Dossier

Scurit

des sessions PHP


Les sessions reposent sur un jeton unique pour reconnatre lutilisateur au cours de sa navigation. Ceci expose les applications des attaques o le pirate usurpe lidentit dun utilisateur lgitime afin daccder au systme dinformation. Dans cet article vous apprendrez scuriser les sessions.
Cet article explique :
Les vulnrabilits lies l'utilisation de sessions. Comment protger les applications reposant sur des sessions.

Ce quil faut savoir :


Vous devez connatre les bases du langage PHP, les cookies et les sessions.

es applications web sont la cible dattaques diverses. Celles-ci visent le systme dinformation ou la prise de contrle du serveur hbergeant lapplication afin dattaquer dautres sites ou dinstaller des services. Les attaques dun systme dinformation attentent : l'intgrit des donnes, la personne malveillante modie les donnes publies sur un site web (dguration) ou modie des informations de l'application ; la condentialit des donnes, le pirate obtient des donnes condentielles sur les utilisateurs (numro de scurit sociale, numro de carte bancaire, coordonnes, ), sur les visiteurs du serveur web (accs aux logs) ou sur le serveur (accs aux chiers de mots de passe et de conguration) ; la disponibilit des donnes en bloquant l'accs un service (dni de service sur le site web ou la base de donnes) ou un utilisateur en particulier.

veillante peut porter atteinte l'intgrit, la confidentialit et la disponibilit des donnes. Cet article prsente le principe du dtournement de session ainsi que les protections mettre en oeuvre contre les attaques ddies l'obtention d'un jeton de session valide (prdiction, force brute, vol et fixation). Un exemple minimal de gestion de session illustre cet article. Son but est de montrer les rglages de scurit. Il comporte 4 scripts : outils_session.php (Listing 1) dnit les fonctions de manipulation de session (ouverture, destruction, vrication de la validit) ; deconnexion.php (Listing 2) ralise la dconnexion de lapplication ; auth.php (Listing 3) gre lauthentication de lutilisateur (afchage du formulaire, contrle des identiants, mise en session des informations) ; liste.php (Listing 4) donne un exemple de script de lapplication, il afche un message et fournit

Les attaques lies aux sessions visent accrotre le niveau de privilge dans une application web protge. Elles peuvent tre le fait d'un utilisateur malveillant authentifi dans l'application ou d'un utilisateur non authentifi qui vole la session d'un utilisateur authentifi. Une fois que le pirate a augment son niveau de privilge, il a accs aux mmes donnes que l'utilisateur victime du dtournement de session. En fonction du niveau de privilge de l'utilisateur, la personne malwww.phpsolmag.org

Figure 1. Principe du dtournement de session.


23

Scurit des sessions

Listing 1. Outils_session.php
<?php // chemin de validit de la session (chane) de ne('CHEMIN', '/appli/'); // communication crypte (booleen) de ne('HTTPS', true); // dure de validit d'une session en secondes (entier) de ne('DUREE', 1200); // URL des scripts principaux de ne('URL _ APPLI', 'https://'.$ _ SERVER['SERVER _ NAME']. CHEMIN); de ne('URL _ AUTH', URL _ APPLI.'auth.php'); de ne('URL _ INDEX', URL _ APPLI.'index.php'); de ne('URL _ ERROR', URL _ APPLI.'error.php'); /** * Rgle les options de session et dmarre la session. */ function initSession(){ // utiliser les cookies uniquement ini _ set("session.use _ cookies", 1); ini _ set("session.use _ only _ cookies", 1); ini _ set('session.use _ trans _ sid', 0); /* xer les proprietes du cookie : arg 1 = detruire le cookie quand le navigateur est quitte, arg 2 = chemin de validite, arg 3 = garder le domaine par defaut, arg 4 = interdire la transmission en clair (uniquement si https), arg 5 = ajouter la propriete HttpOnly */ session _ set _ cookie _ params(0, CHEMIN, '', HTTPS, true); // envoyer le cookie de session PHP, ou restaurer la session session _ start(); } /** * Efface les informations de la session. */ function detruireSession(){ // supprimer le cookie de session setcookie(session _ name(), '', time()-3600, CHEMIN, '', HTTPS, true); // supprimer les variables de session $ _ SESSION = array(); // fermer la session session _ destroy(); }

/** * La session est valide si la personne s'est authentie et si l'heure est * infrieure celle en session. * @return vrai si la session est valide, faux sinon. */ function isSessionValide(){ return (isset($ _ SESSION['login']) && isset($ _ SESSION['timeout']) && (time() < $ _ SESSION['timeout'])); } /** * Vrie si le groupe a le droit d'accder a la ressource demande. * @param $ressource string ressource demande * @param $groupe string groupe de l'utilisateur connect * @return vrai si l'accs est autoris, faux sinon. */ function isAutorise($ressource, $groupe){ // vrication des privilges dans la base } /** * Dmarre ou restaure la session et vrie sa validit, en cas de problme * redirige vers le formulaire d'authentication. Vrie ensuite que le * groupe a le droit d'accder la ressource demande, si problme redirige * vers une page d'erreur. */ function verieAutorisation(){ // initier ou restaurer la session initSession(); // verier la validite de la session if (!isSessionValide()){ // supprimer la session detruireSession(); // rediriger vers la page d'authentication header('Location:'.URL _ AUTH); exit; } else if (!isAutorise(basename($ _ SERVER["SCRIPT _ NAME"]), $ _ SESSION['groupe'])) { // rediriger vers une page d'erreur header('Location:'.URL _ ERROR); exit; } } ?>

un menu comportant un lien de dconnexion. Si la session nest pas valide, lutilisateur est redirig automatiquement vers le script dauthentication.

Principe du dtournement de session

Les sessions reposent sur un identifiant unique envoy par lapplication web lutilisateur. Ce jeton de session est ensuite transmis lapplication par le navigateur lors de chaque requte HTTP. Lidentifiant peut tre plac dans la partie requte de lURL ou dans un cookie de session. Les cookies et le mcanisme des sessions ont t prsents dans deux numros de ce mme magazine ; pour en savoir plus veuillez vous reporter aux articles intituls Manipuler les cookies avec PHP (PHP Solutions 4/2010) et Manipuler les sessions avec PHP (PHP Solutions 6/2010). Le mcanisme des sessions reposant sur un jeton, le pirate doit fournir un jeton de session valide pour dtourner une session dun utilisateur authentifi (session hijacking). Dans la Figure 1, un utilisateur lgitime sauthentifie sur le serveur (a), lapplication lui envoie le
24

jeton de session dont le nom est sessid et la valeur eh26 (b) ainsi que la page demande. Le navigateur retourne automatiquement le jeton de session au cours de la navigation (c). Lors de chaque requte lapplication vrifie que lutilisateur sest pralablement authentifi et a des privilges sur les ressources demandes grce au jeton de session. Par exemple, si lapplication est un CMS et que lutilisateur connect a des privilges ddition, le fait denvoyer le jeton de session lui permet dditer, de supprimer ou de crer des articles. Si un pirate obtient la valeur du jeton de session et quil envoie ce jeton ainsi quune requte au serveur (d), alors il pourra lgitimement supprimer ou modifier des articles. La transmission du jeton de session peut tre ralise dans lURL ou dans un cookie, en fonction des proprits dfinies pour la session. Dans le premier cas il suffit que le pirate modifie la valeur du jeton dans la chane de requte pour envoyer la valeur souhaite au serveur. Dans le second cas, il faut que le pirate intercepte la requte avant lenvoi, afin dajouter ou modifier le cookie, en utilisant un proxy ou un plugin ddi dans
8/2010

Dossier

Listing 2. deconnexion.php
<?php // inclure les fonctions require _ once 'outils _ session.php'; // restaurer la session initSession(); // dtruire la session courante detruireSession(); // message de dconnexion echo 'Deconnexion OK'; ?>

un navigateur. Il est parfois galement possible dexploiter une faille XSS de lapplication pour la forcer placer le cookie souhait dans le navigateur du pirate.

Utilisez les jetons PHP

Listing 3. auth.php
<?php // ouvrir une session require _ once 'outils _ session.php'; initSession(); /** * Filtre les donnes. * @param $var string donnes ltrer * @return string donne ltre */ function lterInput($var){ // opration de ltrage implmenter return $var; } /** * Vrie le login et le mot de passe, rcupre le groupe de l'utilisateur * @param $login string login de l'utilisateur * @param $pwd string mot de passe de l'utilisateur * @param $groupe string groupe de l'utilisateur * @return vrai si les identiants sont corrects, faux sinon */ function verifLogin($login, $pwd, &$groupe){ // opration de vrication implmenter } /** * Afche le formulaire d'authentication */ function afcheFormLogin(){ echo "<form action='auth.php' method='POST'> <input type='text' name='login'> login<br> <input type='password' name='pwd'> password<br> <input type='submit' value='controler'> </form>"; } // Si on a reu des donnes du formulaire, faire l'authentication if (isset($ _ POST['login']) && isset($ _ POST['pwd'])){ // ltrer les entres utilisateur $p _ login = lterInput($ _ POST['login']); $p _ pwd = lterInput($ _ POST['pwd']); $groupe = null; // vrier le login et rcuperer le groupe if (verifLogin($p _ login, $p _ pwd, $groupe)){ // regnrer le jeton de session session _ regenerate _ id(); // xer l'heure d'expiration $ _ SESSION['timeout'] = time() + DUREE; // stocker le login et le groupe $ _ SESSION['login'] = $p _ login; $ _ SESSION['groupe'] = $groupe; // rediriger vers la page principale de l'application header('Location:' .URL _ INDEX); exit; } else { echo '<div class="erreur">identiants incorrects</div>'; afcheFormLogin(); } } else { afcheFormLogin(); } ?>

Par dfaut PHP gnre automatiquement un jeton de session alatoire comportant un grand nombre de caractres. Afin de protger les applications des attaques par prdiction didentifiant de session et des attaques par force brute, il est conseill de ne jamais fixer la valeur du jeton de session dans lapplication et de dlguer cette responsabilit PHP. Aucune application web PHP ne devrait reposer sur des jetons de session dont les valeurs sont dfinies par le dveloppeur, il ne faut donc jamais fixer la valeur du jeton de session avec la fonction PHP session_id. Les attaques par prdiction reposent sur la prdiction dun jeton de session valide, cest--dire que le pirate devine lidentifiant de session utiliser. Cest le cas lorsque la valeur du jeton est un nombre entier incrment chaque ouverture de session. Par exemple, lapplication attribue au premier utilisateur authentifi lentier 101, au second utilisateur lentier 102, au troisime lentier 103, etc. Un utilisateur lgitime de lapplication, par exemple lutilisateur qui a le jeton 103, peut ainsi deviner le systme de numrotation et dtourner la session dun autre utilisateur en transmettant le jeton 101 ou 102. Pour se protger de ces attaques, il faut que lidentifiant de session soit alatoire, ce qui est le cas des jetons gnrs automatiquement par PHP. Les attaques par force brute consistent utiliser un processus automatique pour trouver la valeur dun jeton de session valide. Un programme dattaque par force brute envoie un grand nombre de requtes HTTP par secondes. Il peut ainsi tester des millions de combinaisons et forger un jeton de session valide si le jeton ne comporte pas assez de bits. Pour se protger de ces attaques, il faut que le jeton de session soit alatoire et quil comporte suffisamment de caractres. La meilleure protection est donc dutiliser les jetons PHP. Dans cet article, le nom et la valeur du jeton de session ont t abrgs pour simplifier les exemples. Seuls les quatre premiers caractres du jeton de session sont affichs. Le nom du jeton de session utilis est sessid, par dfaut PHP gnre un jeton de session PHPSESSID (ce nom dpend de la valeur de la directive session. name du fichier php.ini).

Transmettez le jeton dans un cookie

PHP accepte deux mcanismes de transmission du jeton de session. Le jeton peut tre communiqu dans un cookie ou dans la chane de requte de lURL. Lutilisation de lURL pour transmettre le jeton pose des problmes de scurit importants car le jeton est stock sur le client et sur un ou plusieurs serveurs. Le jeton transmis par URL apparat dans la barre dURL du navigateur, derrire le caractre point dinterrogation.
25

www.phpsolmag.org

Scurit des sessions

Par exemple, si lutilisateur demande la ressource liste. php situe dans le rpertoire appli du serveur web www. monSiteWeb.fr, lURL contient dans la chane de requte le nom du jeton de session (sessid) et sa valeur (eh26) : http://www.monSiteWeb.fr/appli/liste.php?sessid=eh26. LURL est stocke dans lhistorique de navigation. Elle peut galement tre stocke dans un signet si lutilisateur en cre un. Si lordinateur est utilis par un tiers (ordinateur dans un cyber caf, par exemple) et que la session na pas t dtruite par une dconnexion, alors laccs la session sera possible partir de lhistorique ou du signet pour tout autre utilisateur de lordinateur. Les serveurs web stockent dans un fichier de logs la premire ligne de chaque requte HTTP reue, la date et lheure de la requte, ainsi que ladresse IP de lordinateur qui a mis la requte. La premire ligne dune requte HTTP GET ou POST contient lURL de la ressource demande. Par exemple, lorsque la ressource liste.php est demande, la requte HTTP envoye au serveur est la suivante :
GET /appli/liste.php?sessid=eh26 HTTP/1.1 Host: www.monSiteWeb.fr

Dans cet exemple, le fichier de logs contiendra donc le jeton de session valide sessid=eh26. Il peut arriver quun pirate visualise le contenu du fichier de logs en exploitant une faille dexcution de commande. Il peut galement obtenir les URL demandes par le biais dapplications qui ralisent des statistiques de frquentation. Si une telle application est installe sur le serveur web et que son accs nest pas protg, alors les jetons de session peuvent tre obtenus facilement par un utilisateur malveillant en consultant les statistiques. Le jeton plac dans lURL peut galement tre stock dans les logs dautres serveurs que celui qui hberge lapplication. Cest le cas par exemple si un proxy est utilis. Enfin, si lapplication web contient un lien vers une page web externe, le jeton pourra tre lu dans le HTTP_REFERER du lien externe (URL de la page partir de laquelle lutilisateur a accd la ressource courante). Afin dviter toutes ces expositions du jeton de session, il faut imposer PHP la transmission du jeton dans un cookie. Lorsque le jeton est transmis par cookie, lURL pour obtenir la page liste.php ne contient plus le jeton : http://www.monSiteWeb.fr/appli/liste.php. La requte HTTP envoye au serveur est la suivante :
GET /appli/liste.php HTTP/1.1 Host: www.monSiteWeb.fr Cookie:sessid=eh26

sions, il faut attribuer la valeur 1 aux directives session. use_only_cookies et session.use_cookies et la valeur 0 la directive session.use_trans_sid. Ces directives ont t dcrites dans larticle ddi la manipulation des sessions ; veuillez-vous reporter cet article pour plus dexplications. Les valeurs des directives peuvent tre fixes dans le fichier php.ini de configuration PHP ou dans les scripts de lapplication. Dans le premier cas, toutes les applications du serveur qui reposent sur les sessions seront alors concernes. Dans le second cas, le rglage sera local lapplication et devra intervenir avant louverture de la session ralise par linstruction session_start. La fonction initSession du Listing 1 fixe les valeurs des directives en utilisant la fonction PHP ini_set, puis elle dmarre ou restaure la session. Elle est appele par la fonction verifieAutorisation du mme Listing. Cette dernire contrle la validit de la session aprs sa restauration. Si la session nest pas valide, la fonction redirige vers le script grant lauthentification de lutilisateur. Tous les scripts de lapplication web incluent le Listing 1 et appelent la fonction verifieAutorisation, sauf les scripts dauthentification et de dconnexion qui nont pas contrler la validit de la session. Ces derniers appellent directement la fonction initSession. Lutilisation dune fonction ddie louverture de la session dans tous les scripts, permet de sassurer que lapplication fonctionnera uniquement avec des jetons transmis par cookie, quels que soient les rglages effectus par ladministrateur systme du serveur web dans le fichier php.ini.

Ne transmettez pas le jeton en clair

Le fichier de log ne contient donc plus le jeton de session et ce jeton napparat plus dans lURL. Afin de forcer PHP utiliser uniquement des cookies pour les ses26

Lorsque lapplication web utilise le protocole HTTP, les communications ne sont pas cryptes. Cest--dire que si les changes entre le client et le serveur sont intercepts par un tiers, les contenus des requtes et des rponses apparaissent en clair. Les logins et mots de passe, les jetons de session, ainsi que les informations confidentielles (numro de scurit sociale, coordonnes, ) ne sont donc pas protgs. Pour viter linterception de jeton par coute du rseau, il faut utiliser une connexion crypte (SSL). Lorsque les donnes transmises sont sensibles (numro de carte bancaire, numro de scurit sociale, jeton de session, ), les communications devraient toujours tre cryptes. Si les changes entre le client et le serveur sont effectus par le protocole HTTPS, cest--dire si lURL commence par https://, alors la communication est crypte. Si vous bnficiez dune communication scurise vous pouvez, pour plus de scurit, rgler la proprit de cookie secure afin dinterdire lenvoi de cookies lorsque la communication nest pas tablie en HTTPS. Si lapplication est accessible la fois par les protocoles HTTP et HTTPS, ce rglage vite que les cookies de session soient envoys en clair. Le rglage peut
8/2010

Dossier

tre effectu dans le fichier de configuration PHP ou dans les scripts de lapplication. Dans le premier cas, il suffit de donner la valeur on la directive session. cookie_secure du php.ini. Dans le second cas, il est possible deffectuer le rglage en utilisant la fonction ini_set, ou en passant la valeur true lavant-dernier argument de la fonction session_set_cookie_ params. Ces fonctions ont t dcrites dans larticle sur les sessions ; veuillez vous reporter cet article pour plus dinformations. La fonction initSession du Listing 1 rgle les proprits des cookies en utilisant la fonction session_set_cookie_params.

Protgez les cookies des attaques XSS

Bien que la transmission du jeton de session par cookie soit la mthode la plus sre, le cookie de session peut lui-mme tre lobjet dun vol. Il peut tre obtenu par un pirate via une attaque XSS. Le XSS (Cross Site Scripting) consiste injecter un contenu actif dans un document HTML. Par exemple linjection du code JavaScript alert(document.cookie) provoquerait laffichage dans le navigateur de la victime dune fentre dalerte contenant les cookies pour le domaine et le chemin de la page demande. Gnralement le pirate injecte un code XSS qui provoque lenvoi du cookie un serveur distant, o le pirate pourra rcuprer ultrieurement le jeton de session et lURL de lapplication web concerne par le jeton. Toute donne provenant dun utilisateur est susceptible de contenir des chanes de caractres malicieuses qui ont un sens pour un interprteur JavaScript. La rgle est de ne jamais faire confiance aux donnes envoyes par le client. Le filtrage des donnes sur le serveur est la premire tape assurant le bon fonctionnement de lapplication ainsi que la scurisation de lapplication et du systme qui lhberge. Il faut vrifier les donnes en entre mais aussi traiter les donnes avant de les envoyer au client, notamment en utilisant la fonction htmlentities. Pour protger les cookies de session des attaques XSS, il faut donc filtrer les entres de lapplication et protger ses sorties. Afin de lutter contre le vol des cookies de session, la proprit HttpOnly peut tre ajoute dans le champ Set-Cookie de len-tte de la rponse HTTP. Celle-ci indique au navigateur quil nest autoris transmettre le cookie que dans les requtes HTTP, le cookie ne peut pas tre lu ou modifi depuis un script sur le client. Par exemple, la ligne ci-aprs de la rponse HTTP envoie un cookie de session sessid dont laccs depuis JavaScript est interdit :
Set-Cookie: sessid=eh26; HttpOnly

la version 5.2.0, PHP peut ajouter cette proprit automatiquement lors de lenvoi du cookie de session au navigateur. La prsence de cette proprit dans le champ den-tte HTTP dpend de la valeur de la directive session.cookie_httponly du fichier de configuration php.ini (valeur on pour ajouter httponly). Il est galement possible dindiquer PHP dajouter cette proprit en affectant le boolen true au dernier argument de la fonction session_set_cookie_params (cf. fonction initSession du Listing 1). Bien quutile, cette proprit nest pas suffisante pour garantir la protection des cookies de session. Dune part elle nest pas implmente dans tous les navigateurs, car elle nest pas standard. Dautre part, des contre-mesures ont t trouves par les pirates pour dtourner des cookies comportant la proprit HttpOnly (attaques XST). Vous ne devez donc pas faire reposer la scurit du cookie de session uniquement sur cette proprit.

Fixez le chemin de validit du cookie

Avant denvoyer un cookie, le navigateur vrifie son chemin. Si la ressource demande na pas le mme chemin, alors le cookie nest pas envoy. Si le chemin est trop gnral, lapplication est susceptible dtre attaque par le biais dautres applications sur le mme serveur. Par exemple, si le chemin du cookie de session est dfini sur la racine du serveur web, et non pas sur celle de lapplication, le cookie sera envoy par le navigateur toutes les ressources demandes sur le serveur qui hberge lapplication. Ceci augmente le risque de vol du cookie. Par dfaut, le chemin des cookies envoy par PHP est la racine du serveur web (caractre /). Il est dfini par la directive session.cookie_path du fichier php. ini. Pour restreindre la validit au chemin de lapplication, dfinissez le chemin avec la fonction session_ set_cookie_params. Ceci devra tre fait avant lappel la fonction session_start. Dans le Listing 1, le chemin de validit est celui du rpertoire appli qui contient lapplication web, il est dfini par la constante CHEMIN. La proprit est fixe dans la fonction initSession. Lapplication est situe la racine du serveur web, le chemin est donc /appli/. Le caractre / aprs le nom du rpertoire vite que le cookie soit envoy dautres rpertoires qui commenceraient par la sous-chane appli.

Grez la dconnexion

Lorsque cette proprit est supporte par le navigateur, lexcution du code JavaScript alert(document. cookie) ne montre plus le cookie de session. Depuis
www.phpsolmag.org

Il est important de fournir lutilisateur un lien ou un bouton de dconnexion sur chaque page de lapplication web. Pour tre efficace, la procdure de dconnexion doit supprimer le fichier de session, effacer les variables de session, envoyer un cookie de session vide et dont la date limite est dpasse. La fonction detruireSession du Listing 1 ralise toutes ces oprations. Pour effacer
27

Scurit des sessions

un cookie il faut en envoyer un de mme nom, de mme domaine et de mme chemin. Dans cette fonction, le nom du jeton de session est obtenu grce la fonction session_name. Le cookie envoy a une valeur vide et une date de validit antrieure dune heure lheure courante. Le chemin de validit du cookie est celui du rpertoire appli, il doit tre identique au chemin donn dans la fonction initSession. La destruction de la session courante ne peut tre ralise que si la session a t restaure pralablement. Le script deconnexion.php du Listing 2 effectue la restauration puis la dconnexion. Ceci permet de dtruire entirement les informations de la session courante. Si lutilisateur sest dconnect et que la dconnexion ralise les trois oprations dcrites ci-avant, alors la session ne sera plus exploitable ultrieurement par un pirate qui a intercept le jeton.

Limitez la dure de vie de la session

Un pirate peut voler un cookie de session par une attaque XSS, en exploitant un bug dun navigateur, en coutant le rseau ou dans le gestionnaire de session du navigateur lorsque lordinateur est partag par plusieurs utilisateurs. Une fois le cookie obtenu, le dtournement de session ne sera possible que si la session est encore active, cest--dire si lutilisateur ne sest pas dconnect ou si lapplication ne gre pas correctement la procdure de dconnexion dcrite dans la section prcdente. Beaucoup dattaques sont possibles car les donnes de sessions restent prsentes sur le serveur web. Plus la dure de validit dune session est courte, plus il sera difficile pour un pirate de dtourner la session dun utilisateur. Afin de limiter lutilisation dun jeton intercept, il est utile de mettre en place dans lapplication web un contrle de la dure de validit. Il est conseill de stocker lheure limite de validit de la session dans une variable de session et de vrifier chaque requte de lutilisateur que cette heure limite nest pas dpasse. Afin de ne pas bloquer lutilisateur lgitime, vous pouvez actualiser lheure limite au cours de la navigation. La dure de validit dpend du niveau de scurit de lapplication. LOWASP (Open Web Application Security Project) recommande une dure de 20 minutes pour les applications non sensibles, et de 5 minutes pour les applications sensibles. Le script auth.php du Listing 3 gre lauthentification de lutilisateur. Lorsque les identifiants de connexion sont corrects, il cre une variable de session timeout qui stocke lheure laquelle la session ne sera plus valide. La dure de validit est fixe 20 minutes par la constante DUREE du Listing 1. La fonction isSessionValide du Listing 1 est appele par la fonction verifieAutorisation. Tous les scripts de lapplication prennent donc les mmes options de session, dmarrent la session et contrlent sa validit. Chaque page de lap28

plication web est protge, elle nest accessible que si lutilisateur a une session en cours. La fonction isSessionValide vrifie que lutilisateur sest pralablement authentifi (la variable de session login existe) et que lheure dexpiration nest pas atteinte. Dans les exemples de cet article la validit de la session est de vingt minutes, quelles que soient les oprations ralises au cours de la navigation. En fonction du niveau de scurit de lapplication, vous pouvez actualiser lheure de fin de validit chaque fois que lutilisateur ralise une opration, afin de lui viter une dconnexion vingt minutes aprs la phase dauthentification. Par ailleurs, il est conseill de limiter la dure de vie des cookies de session dans le navigateur. Ceux-ci doivent tre imprativement dtruits lorsque le navigateur est quitt. Ceci est ralis en attribuant la valeur 0 la directive session.cookie_lifetime du fichier php. ini ou en affectant la valeur 0 au premier argument de la fonction session_set_cookie_params (cf. fonction initSession du Listing 1).

Rgnrez le jeton de session

Plutt que de voler le jeton de session ou de le deviner, le pirate peut imposer un utilisateur dutiliser un jeton. Une fois la victime authentifie, le pirate utilise ce jeton pour usurper son identit. Pour comprendre cette attaque, il faut tout dabord savoir comment PHP gre une session. Lorsquun utilisateur demande une ressource dune application web utilisant le mcanisme des sessions, PHP vrifie la prsence dun jeton de session. Si celui-ci est prsent, il cherche les donnes pour cette session. Sil ny en a pas, il cre un fichier de session pour le jeton. Lapplication vrifiant gnralement la prsence dune variable de session pour dterminer si la personne est correctement authentifie, lutilisateur est redirig vers un formulaire dauthentification. Une fois lauthentification effectue, lutilisateur conserve le jeton de session pendant la dure de sa navigation. Lacceptation par PHP dun jeton de session avant lauthentification permet un pirate dusurper lidentit dun utilisateur lgitime, ds lors quil russit imposer ce jeton de session la victime. Plusieurs mthodes peuvent lui permettre darriver ses fins. Les attaques par fixation du jeton de session sont facilites par la transmission du jeton dans lURL. Dans ce cas, le pirate peut facilement ajouter le jeton dans un lien sur lequel la victime cliquera. Il peut galement exploiter une faille XSS pour ajouter un champ cach sessid dans le formulaire dauthentification de lapplication. Le pirate peut aussi crer un formulaire de login contenant le jeton sur un autre serveur que celui de lapplication et lenvoyer lapplication. Ceci est une raison supplmentaire de ne pas accepter les jetons de session par URL et de leur prfrer les cookies (directive session.use_cookies = 1).
8/2010

Dossier

Quand la transmission par cookie est utilise, PHP cherche tout dabord si un jeton de session est prsent dans les cookies. Si ce nest pas le cas, il en cherche un dans lURL. Un exemple typique dattaque est le suivant. Lutilisateur clique sur un lien vers lapplication web, celui-ci contient un jeton de session dont la valeur est eh26. Ce peut tre un lien plac par le pirate dans un mail ou dans une page web. Le script dauthentification cre une session pour ce jeton et retourne un formulaire dauthentification. Ce dernier comporte le jeton de session dans un champ cach gnr automatiquement, si la directive session.use_trans_sid a la valeur 1. En PHP4, un cookie dont la valeur est eh26 est retourn en mme temps que le formulaire ; ce nest plus le cas avec PHP5. Le formulaire est rempli par lutilisateur, sa validit est vrifie et les variables de session sont cres. Le pirate peut maintenant se connecter sur le site en utilisant lidentifiant quil avait fix. Afin dinterdire la prise en compte du jeton pass dans lURL, il faut veiller ce que la directive session. use_only_cookies soit active. Il faut galement dsactiver la compltion automatique des URL avec la directive session.use_trans_sid (cf. Listing 1). Avec les deux rglages prconiss, le pirate ne peut plus imposer le jeton de session par le biais de lURL. Limiter la transmission des jetons uniquement par cookies nest pas une protection suffisante contre les attaques par fixation. Un pirate peut en effet exploiter une faille de scurit de lapplication web (XSS, HTTP Response Splitting) pour quun serveur web place un cookie dans le navigateur de la personne dont il veut dtourner la session. Ces attaques reposant sur un identifiant de session fix par le pirate, il suffit de rgnrer un nouvel identifiant de session lorsquil y a un changement de niveau de privilge (utilisateur authentifi, passage en mode administration, ). Lutilisation de la fonction PHP session_regenerate_id une fois lauthentification effectue permet de protger lapplication. Cette fonction produit un nouveau jeton de session et lenvoie au navigateur. Dans la mesure o cette fonction envoie un cookie, il faut veiller ne pas envoyer de donnes avec echo, print, avant de lappeler. Depuis PHP 5.1 la fonction accepte un argument boolen indiquant sil faut supprimer (true) la vieille session. Par dfaut elle est conserve. Le Listing 3 effectue la rgnration du jeton de session une fois que lutilisateur sest authentifi.

Protgez les donnes de session

Afin de mmoriser les informations de session pendant toute la dure de navigation dun internaute, celles-ci sont stockes dans un fichier temporaire sur le disque dur du serveur web. Lapplication web grant simultanment plusieurs utilisateurs, un fichier est cr par session. Le nom du fichier de session contient la valeur du jeton de session, prfix par sess. Ces fichiers sont gnralement stocks dans un rpertoire temporaire, dont
www.phpsolmag.org

lemplacement est dfini par la directive session.save_ path du fichier php.ini. Si un utilisateur malveillant a accs ces fichiers de session, il peut obtenir les valeurs des jetons de session partir des noms de fichiers, il peut galement accder aux donnes de session contenues dans ces fichiers. La consultation et lcriture de fichiers de session est le plus souvent ralise en interne par un utilisateur qui a accs au serveur web en ssh ou sftp. Cependant une faille dinjection (inclusion de fichier, excution dans un shell) peut galement permettre laccs ces fichiers un pirate qui na aucune autorisation daccs au serveur web. Il devient ainsi possible dobtenir un identifiant de session valide ou de crer une session (cration du fichier), mais galement de voler des informations sensibles contenues dans le fichier de session. Si aucun utilisateur na accs au serveur web par ssh ou sftp en dehors de ladministrateur, il faut protger les applications web des failles dinclusion de fichier et dexcution de shell pour viter quun utilisateur malveillant obtienne des jetons de session valides partir des noms des fichiers de session. Si possible, il faut interdire lexcution de commandes telles que system, exec avec la directive disable_functions du php.ini. La meilleure protection pour interdire laccs aux donnes de session et lexposition de la valeur du jeton de session, est de ne plus les stocker dans des fichiers. Deux solutions sont envisageables : stocker les informations dans une base de donnes ou en mmoire. Dans le premier cas, lapplication doit dfinir son gestionnaire de session, cest--dire quil faut fournir les fonctions pour stocker et manipuler les donnes dans la base. Les fonctions crire seront appeles lors de louverture et de la fermeture de la session, lors de la lecture et de lcriture de donnes en session (variable $_SESSION), et lors de la fin dexcution du script. La fonction session_set_save_handler permet dindiquer les noms des fonctions du gestionnaire de session. Elle doit tre appele avant de dmarrer la session. La seconde solution est plus simple mettre en place, car elle ne demande aucune cration de fonction. Elle repose sur un serveur memcached et sur lextension memcache (memcache.so ou memcache.dll). Celle-ci se charge de la mise en cache et de la rcupration des donnes de session. Ladministrateur systme doit installer un serveur memcached et lextension memcache pour PHP. Il suffit ensuite de dfinir les deux directives du php.ini :
session.save_handler = memcache session.save_path = tcp://IP_serveur_memcached: port_memcached?persistent=1

Il est galement possible de combiner cette solution avec celle de lutilisation dune base de donnes afin davoir un gestionnaire de session tout le temps oprationnel,
29

Scurit des sessions

mme lorsque le serveur memcached ne rpond pas. Pour ce faire il faut programmer son propre gestionnaire de session, cest--dire dfinir les fonctions dcrites prcdemment et utiliser session_set_save_handler.

Listing 4. liste.php
<?php // restaurer la session require _ once 'outils _ session.php'; verieAutorisation(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Liste</title> </head> <body> <div>Une liste ...</div> <div> <a href='deconnexion.php'>deconnexion</a> </div> </body> </html>

Utilisez un moyen didentification secondaire

Le jeton de session est le premier moyen didentification. Il peut tre combin un autre moyen dauthentification pour les applications sensibles. Celui-ci ne peut pas reposer sur ladresse IP car, dune part, celle-ci peut varier au cours dune session valide dun utilisateur en fonction des choix de linfrastructure rseau effectus par le fournisseur daccs, et dautre part lorsquun proxy est utilis dans lentreprise, plusieurs utilisateurs dun mme rseau peuvent avoir la mme adresse IP (translation dadresse). Dans le premier cas, invalider une session lorsque ladresse IP change bloquerait la navigation dun utilisateur lgitime. Dans le second cas, des tentatives dusurpation de session par un pirate situ sur le mme rseau que la victime passeraient inaperues. Il est possible dutiliser le champ User-Agent de len-tte HTTP comme moyen didentification secondaire. Ce champ optionnel contient le nom et la version du navigateur utilis par linternaute. Si lapplication reoit un jeton de session mais que le navigateur qui la envoy nest pas celui qui a initi la session, alors il est fort probable que ce soit une tentative de dtournement de session. La session tant lie un cookie plac dans un navigateur, le jeton devrait toujours tre transmis par le mme navigateur pendant toute la dure de la session. Lors de la phase dauthentification, certains dveloppeurs stockent le contenu du champ User-Agent dans une variable de session. Ce champ tant prsent dans la requte HTTP, il est susceptible de contenir des donnes malicieuses, comme toute autre entre utilisateur. Il est donc conseill dutiliser la fonction md5 afin de simplifier les comparaisons ultrieures :
$_SESSION['agent'] = md5($_SERVER['HTTP_USER_ AGENT']);

Listing 5. Modi cation de la fonction isSessionValide


/** * La session est valide si la personne s'est authentie, si l'heure est * infrieure celle en session, et si le jeton alatoire est dans l'URL * et est identique celui en session. * @return vrai si la session est valide, faux sinon. */ function isSessionValide(){ $g _ id = (isset($ _ GET['id'])) ? trim($ _ GET['id']) : null; return (isset($ _ SESSION['login']) && isset($ _ SESSION['timeout']) && (time() < $ _ SESSION['timeout']) && !empty($g _ id) && !empty($ _ SESSION['id']) && ($g _ id == $ _ SESSION['id'])); }

Lors de chaque requte, lapplication vrifie si la personne sest authentifie (prsence dune variable de session), si la session na pas expir et si le MD5 du navigateur qui a mis la requte est identique celui stock en session. En cas de problme, lapplication demande lutilisateur de sauthentifier. Il faut noter cependant que si le pirate utilise le mme navigateur, il ne sera pas bloqu par cette mesure dauthentification secondaire. De plus, le nom et la version du navigateur peuvent tre obtenus facilement en JavaScript. Linstruction JavaScript alert(navigator.userAgent) affiche le nom et la version du navigateur dans les principaux navigateurs utiliss actuellement (Firefox, Internet Explorer, Safari, Chrome, Opera). La chane retourne
30

par cette instruction est identique celle transmise par le navigateur dans la requte HTTP. Si le pirate a exploit une faille XSS pour obtenir le cookie, il peut facilement obtenir par ce biais les informations de version. Il lui suffit ensuite de remplacer la valeur du champ den-tte User-Agent dans la requte envoye par son navigateur. Des outils permettent dintercepter et modifier les requtes trs facilement. Utiliser linformation contenue dans le champ User-Agent nest donc pas une mesure de protection supplmentaire suffisante. Une autre approche consiste propager une chane alatoire pendant toute la session. Utilise en conjonction avec une connexion crypte, la chane aide sassurer que la personne qui vient denvoyer le jeton de session est bien celle qui sest authentifie. La chane peut tre transmise par cookie, mais dans ce cas elle risque dtre elle-mme intercepte si le jeton a t obtenu par un XSS. Il est prfrable de toujours transmettre le jeton de session dans un cookie et la chane alatoire dans lURL. Lors de lauthentification il faut gnrer et stocker en session lidentifiant alatoire unique, aprs avoir rgnr le jeton de session :
$_SESSION['id'] = md5(uniqid(rand(), TRUE)); 8/2010

Dossier

Il suffit dadapter le Listing 3 en ajoutant cette ligne de code, lorsque lutilisateur a fourni des identifiants valides au formulaire dauthentification. Il faut ensuite ajouter lidentifiant dans tous les liens de lapplication (liens hypertextes, attribut action des formulaires). Par exemple la redirection vers la page principale aprs authentification du Listing 3 devient :
header('Location:'.URL_INDEX.'?id='.$_ SESSION['id']);

dans une base de donnes. La fonction compare les droits daccs et retourne un boolen.

Conclusion

Lorsque lutilisateur met une requte, lapplication doit vrifier comme prcdemment que lutilisateur sest authentifi pralablement (prsence dune variable de session), que lheure dexpiration na pas t dpasse, et que la chane alatoire a bien t envoye et est identique celle stocke dans la variable de session. Le code de la fonction isSessionValide du Listing 1 a t modifi pour prendre en compte cette vrification dans le Listing 5.

Vous savez prsent configurer les directives de scurit des sessions et mettre en place des mcanismes pour protger vos applications dun dtournement de session. Le niveau de protection mettre en oeuvre dpend de lapplication web. Les rgles de base appliquer, quel que soit le niveau de scurit de lapplication web, sont les suivantes : utiliser les jetons gnrs automatiquement par PHP, transmettre le jeton uniquement par cookie, xer un chemin de validit pour le cookie, rgnrer le cookie aprs lauthentication, protger le cookie des attaques XSS, fournir un moyen de dconnexion, limiter la dure de vie de la session, vrier les droits daccs dun groupe dutilisateurs une ressource.

Vrifier les droits daccs

Une application utilisant les sessions comporte en gnral plusieurs groupes dutilisateurs avec diffrents niveaux de privilges. Il est important de vrifier que lutilisateur connect a des droits sur chaque ressource demande. Lors de lauthentification lapplication, le groupe auquel lutilisateur appartient doit tre stock dans une variable de session. Cest ce qui est fait dans le Listing 3. Dans le Listing 1, la fonction verifieAutorisation ouvre la session et vrifie que le groupe de lutilisateur connect a le droit daccs la page demande. Si ce nest pas le cas, lutilisateur est redirig vers une page affichant un message derreur. Cette fonction tant appele au dbut de chaque script de lapplication, toutes les pages sont ainsi protges. Afin de simplifier les listings, le code de la fonction isAutorise, qui effectue la vrification des privilges, nest pas donn dans cet article. En gnral les ressources accessibles pour chaque groupe sont stockes

Toutes ces oprations peuvent tre ralises dans le code de lapplication. Elles ne dpendent donc pas du rglage du serveur web. Si possible, il faut galement utiliser une communication crypte, afin que le jeton et les donnes sensibles ne soient pas transmis en clair. Si lapplication est hberge sur un serveur web dont vous ntes pas ladministrateur, et que celui-ci ne supporte pas le protocole HTTPS, vous ne pourrez malheureusement pas utiliser cette protection. Si lapplication est sensible vous devez en plus : transmettre le jeton et les donnes par le protocole HTTPS, utiliser un moyen didentication secondaire transmis par URL, protger les donnes de session et le jeton en mettant en place un stockage des donnes dans une base de donnes ou en mmoire cache.

Sur Internet
http://www.php.net/manual/en/session.security.php Scurit des sessions dans le manuel o ciel de PHP, http://www.owasp.org/index.php/Session_Management Gestion de la scurit des sessions dans le guide de lOWASP (Open Web Application Security Project), http://www.php.net/manual/fr/book.memcache.php Manuel memcache/PHP, http://www.memcached.org site o ciel de Memcached, http://www.owasp.org/index.php/XST Informations sur le XST dans le guide de lOWASP, http://www.owasp.org/index.php/XSS Informations sur le XSS dans le guide de lOWASP.

CCILE ODERO MAGALI CONTENSIN


Ccile Odero est spcialise dans la conception et le dveloppement dapplications web en PHP. Elle est dveloppeur web freelance. Contact : cecile.odero@gmail.com Magali Contensin est chef de projet en dveloppement dapplications au CNRS. Elle enseigne depuis plus de dix ans le dveloppement dapplications web luniversit et est lauteur de nombreux articles sur le dveloppement web en PHP. Contact : http://magali.contensin.online.fr
31

www.phpsolmag.org

Scurit des sessions

www.sos-hebergement.com Chez nous pas de promesse, que des engagements.

Packs Mutualiss
Configuration partir de : > Plesk : 1 > Espace disque : 2 Go > Trafic mensuel : 50 Go > Base de donnes : 1 > Alias de domaine : 1 > Backup hebdomadaire

Prix : 35 /an*

Construisez lhbergement qui vous ressemble !


Toutes les ressources mises disposition sont garanties et modifiables indpendament pour sadapter vos besoins.

Packs Privs
Configuration partir de : > Plesk : 10 > Ram : 1/2 Go > Processeur : 1/4 Core** > Espace disque jusqu : 10 Go*** > Trafic mensuel : 500 Go/mois
Prix : 12 /mois*

Packs Ddis
Configuration partir de : > Plesk : 30 > Ram : 2 Go > Processeur : 1 Core** > Espace disque jusqu : 50 Go*** > Bande passante garantie : 1 To > Ressources modifiables sparment
Prix : 49 /mois*

Options disponibles
Un large choix doptions est disponible en fonction des packs : - Infogrance - Monitoring - Licence Plesk 1 300 domaines - Disques haute qualit, 10Kt, 15Kt - Ip supplmentaire - Bande passante garantie 100Mbs - Data center Paris ou Amsterdam - Sauvegarde hebdomadaire ou mensuelle dsactivable - CDN , Load Balancing ...

32 www.sos-hebergement.com

contact@sos-hebergement.com

*Prix HT. **1 Core = Un processeur X5570. *** Espace maximum sans 8/2010 sauvegarde.

Dossier

Scurisation

dun rpertoire avec .htaccess et .htpasswd


Protgez les parties sensibles de votre site web, de votre webapp ou de votre intranet grce Apache. Commet limiter laccs grce un couple login/pass.

Cet article explique :


Comment scuriser un dossier grce Apache et nautoriser laccs quaux seuls visiteurs munis dun couple login/pass valide.

Ce quil faut savoir :


Quelques notions de PHP. Con gurer son logiciel FTP. Manipuler les chiers txt.

ur un site internet ou plus encore sur une webapp, il est souvent utile de scuriser un dossier pour en limiter laccs aux seuls utilisateurs autoriss. Apache fournit pour cela une solution trs efficace : la protection par fichier .htaccess et .htpasswd. Par dfaut, tant le rpertoire super-utilisateur que DocumentRoot sont rgls pour permettre la prise en compte des instructions de fichiers .htaccess. La directive AllowOverride du fichier httpd.conf dfinit si des Options peuvent tre invalides par les instructions dun fichier .htaccess. Les fichiers .htaccess sont des fichiers de configuration du serveur Apache, ils permettent de dfinir des rgles dans un rpertoire. On peut les utiliser pour protger un rpertoire par mot de passe, pour changer le nom ou lextension de la page index (page appele par dfaut ; exemple : http://monsite.com/ appelle par dfaut http://monsite.com/idex.html, on peut trs bien changer en http://monsite.com/accueil.html), ou encore pour personnaliser les pages derreur. Le fichier .htaccess est plac dans le rpertoire dans lequel il doit agir. Il agit ainsi sur les permissions du rpertoire qui le contient et de tous ses sous-rpertoires. Nanmoins, cette solution a un dfaut majeure : les mots de passe tant crypts, impossible de retrouver un mot de passe perdu. A dfaut de le retrouver, laide de PHP, nous allons pouvoir crer un module permettant de rinitialiser un mot de passe et de rcrire le .htpasswd la vole. Supposons que votre site www.monsite.com dispose dun espace rserv qui se situe dans le dossier www.
www.phpsolmag.org

monsite.com/admin . Autorisez les droits en criture pour ce dossier (CHMOD 777) afin que nous puissions gnrer le fichier .htpasswd (qui sera lui en CHMOD 644). Nous allons tout dabord crer un fichier .htaccess pour protger celui-ci. Pour cela, ouvrez un simple diteur de texte (Bloc Notes, Vim, Emacs, Gedit, TextWrangler), crez un nouveau fichier vide et copiez-y le code du Listing 1 (modifi selon vos besoins). Vous allez devoir modifier trois de ces lignes :
ErrorDocument 401 : cest le chemin absolu de la

.htaccess

page vers laquelle lutilisateur sera redirig en cas derreur (ne pas mettre cette page dans le rpertoire protg). AuthUserFile : cest le chemin absolu du chier .htpasswd qui contient le mot de passe crypt
Listing 1. .htaccess
ErrorDocument 401 /var/www/vhosts/monsite.com/ httpdocs/401.php AuthUserFile /var/www/vhosts/monsite.com/httpdocs/ admin/.htpasswd AuthGroupFile /dev/nullAuthName "Authentication requise" AuthType Basic <limit GET> require valid-user </Limit>

33

.htaccess et .htpasswd

(mettez-le au mme endroit que le .htaccess, cest plus simple). AuthName : cest le texte qui apparatra dans la boite de dialogue demandant le mot de passe. Si vous ne connaissez pas le chemin absolu de votre fichier, faites ceci : Crez un chier nomm path.php. Insrez ce code PHP : <?php echo realpath('path. php'); ?>. A laide de votre logiciel FTP, placez ce chier dans le mme rpertoire que votre .htaccess. Excutez ce chier dans votre navigateur. Il vous donnera le chemin absolu (/var/www/vhosts/monsite/httpdocs/admin/path.php dans mon cas). Remplacez path.php par .htpasswd et vous obtenez le chemin du .htpasswd. Faites de mme pour votre chier 401.php ( ne pas mettre dans le rpertoire protger, bien sr. Pour bien vous organiser vous pouvez crer un rpertoire error ou erreurs la racine de votre site pour y stocker vos pages personnalises derreur).

Listing 2. Gnrateur de chier .htpasswd


<html> <head> </head> <body> <?php //rcupration des donnes du formulaire $subform=$ _ POST['subform']; $login=$ _ POST['login']; $pass=$ _ POST['pass']; // n de la rcupration // fonction pour crypter le mot de passe $passcrypt=crypt($pass); //nouveau mot de passe crypt // n de la fonction $new="";//nouveau contenu chier .htpasswd if($subform and $login != "" and $pass != ""){// si formulaire ok if (le _ exists("admin/ .htpasswd")) {// si le chier .htaccess existe $handle = fopen("admin/ .htpasswd", "r"); while (!feof ($handle)) { $ligne = fgets($handle, 4096);// on lit le .htaccess existant ligne par ligne $element=explode(":",$ligne);// on dcoupe la ligne pour rcuprer le login et le pass if($element[0]==$ _ POST['login']){// si le login existe dj $new.=$login.":".$passcrypt."\n";// on crase avec le nouveau login $deja=1;// le login existait dj } else{ $new.=$ligne."\n"; } } fclose( $handle ); if($deja==0){$new.=$login.":".$passcrypt;}// si le login n'existait pas, on l'ajoute } else{// si le chier .htaccess n'existe pas $new.=$login.":".$passcrypt."\n"; } $handle = fopen("admin/ .htpasswd", "w+"); fwrite($handle,"$new");// on rcrit le chier .htpasswd fclose( $handle); print("<strong>Mise a jour effectuee.</strong><br />"); } ?> <form action="" method="post" name="form1" id="form1"> <table width="600" border="0"> <tr> <td width="129" valign="middle">Login :</td> <td width="461" valign="middle"><input type="text" name="login" id="login" /></td> </tr> <tr> <td valign="middle">Pass :</td> <td valign="middle"><input type="text" name="pass" id="pass" /></td> </tr> <tr> <td valign="middle">&nbsp;</td> <td valign="middle"><input type="submit" name="subform" id="subform" value="Valider" /></td> </tr> </table> </form> </body> </html>

Enregistrez ce fichier en htaccess.txt puis, avec votre logiciel FTP, placez-le dans le rpertoire protger (vous devez transfrer ce fichier en mode ASCII (voir documentation de votre client FTP pour assurer la conversion des caractres fin de ligne) et renommez-le en .htaccess . Voil pour notre premier fichier.

.htpasswd

Nous allons maintenant crer notre fichier .htpasswd. Pour ce faire, nous allons crer un script PHP (Listing 2) contenant un formulaire permettant dajouter et de modifier les login/pass. Ce fichier fournit un simple formulaire deux champs (login et pass). Une fois valid, deux cas se prsentent : soit le login est inexistant, auquel cas il sera ajout avec le mot de passe choisi (crypt), soit il existe dj, auquel cas le mot de passe sera remplac par le nouveau (crypt). Enregistrez ce fichier creer.php dans le rpertoire parent du dossier protger. Ce script fonctionnera dans 99% des cas, mais il faut noter que selon la configuration de Apache, les mots de passe peuvent tre crypts diffremment. PHP dfinit une constante appele CRYPT_SALT_LENGTH permettant de vous indiquer la longueur du salt disponible pour le systme de hachage utilis. Dans ce cas, essayer de changer : // fonction pour crypter le mot de passe $passcrypt=crypt($pass); //nouveau mot de passe crypt // fin de la fonction
34

8/2010

Dossier

Listing 3. Document derreur 401


<html> <head> <title>Acces restreint</title> </head> <body> Vous n'avez pas l'autorisation d'accder cette partie du site. <br /> Si vous avez perdu votre mot de passe, merci de contacter l'administrateur qui vous rinitialisera celui-ci. <br /><br /> Merci. </body> </html>

Voil, votre dossier est maintenant parfaitement protg. En effet, il nexiste pas de fonction de dchiffrement des mots de passe, car la fonction crypt utilise un algorithme un seul sens (injection). Il ne reste plus qu crer la page vers laquelle les utilisateurs ayant entr un mauvais mot de passe seront redirigs. La premire ligne de notre .htaccess tant
ErrorDocument 401 /var/www/vhosts/monsite.com/ httpdocs/401.php

par // fonction pour crypter le mot de passe


$cset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; $salt = ""; for ($i=0; $i<CRYPT_SALT_LENGTH; $i++) $salt .= substr($cset, rand() & 63, 1); $passcrypt=crypt($pass, $salt);//nouveau mot

La page de redirection se nomme 401.php et se trouve dans le rpertoire parent de notre rpertoire protger (elle ne peut en effet pas tre dans le rpertoire protger puisque les utilisateurs arrivant sur cette page sont ceux qui ont entr un mauvais couple login/pass). Vous pouvez de mme ajouter des lignes dans votre .htaccess pour personnaliser les autres pages derreur (404). Le fichier 401.php peut ressembler au Listing 3 (modifi selon vos besoins).

Conclusion

de passe crypt // fin de la fonction

Largument optionnel salt sera utilis comme base pour le chiffrement. De mme, souvent, sur les serveurs Windows, les mots de passe ne sont pas crypts. Dans ce cas, remplacez par : // fonction mot de passe $passcrypt= $pass; //nouveau mot de passe non crypt // fin de la fonction Excutez ce fichier. Vous pouvez crer autant de couples login/pass que vous le souhaitez. Si un login existe dj, son mot de passe sera cras. Bien entendu, il nest pas conseill de laisser ce fichier creer.php sur le serveur, ou alors de modifier le code (les chemins du fichier .htpasswd) et de lenregistrer dans un autre rpertoire lui mme protg par un unique login/pass que seul ladministrateur connatra. Le plus simple pour un usage classique est de supprimer ce fichier et de le remettre si besoin est.

Voil. Nous avons vu ici comment protger simplement et efficacement un rpertoire. Vous pouvez aller encore plus loin dans la configuration du fichier .htaccess, par exemple en bloquant certaines adresses IP, ou en crant des groupes dutilisateurs Le fichier Apache .htaccess est trs puissant et permet de faire de nombreuses choses.

FRANCK CANONNE
Dveloppeur PHP freelance, Franck Canonne a ralis de nombreux sites web dynamiques avant de se spcialiser dans les webapps et la gestion de bases de donnes MySQL. Touche tout, il prfre aujourdhui utiliser des solutions libres ( Drupal, Wordpress) pour tout ce qui est dveloppement web, et rserve le dveloppement PHP/MySQL AJAX pour les applications riches de gestion de base de donnes. Conscient des contraintes des webapps, il optimise celles-ci en amont par une con guration spci que du serveur Apache hte.
35

Sur Internet
http://httpd.apache.org/docs/2.2/howto/auth.html Documentation Apache, http://aspirine.org/htaccess.html Aspirine : gnration de chier .htaccess.

www.phpsolmag.org

Pratique

Communication
Flash/PHP
Flash, PHP, est-il encore bien ncessaire de les prsenter ? Si largement rpandus que chaque internaute les connat au moins de nom ; leur succs na dgal que leur efficacit. Chacun sa spcialit, chacun son utilisation, runis pour crer des applications alliant lergonomie et le dynamisme des interfaces Flash aux capacits dexploitation serveur offertes par PHP.
Cet article explique :
Faire communiquer une application ash AS2 et un script PHP.

Ce quil faut savoir :


Lenvironnement Flash. ActionScript 2. Le traitement dinformations reues par POST ou GET dans un script PHP.

es animations Flash sont des applications clientes ; sexcutant exclusivement sur le client, il faut, pour les faire interagir avec un serveur distant (MySQL par exemple), un quelque chose faisant le lien. Pour crer ce quelque chose il existe plusieurs solutions : une solution payante, le Flash Media Server (FMS) permettant notamment la communication par socket ; des solutions gratuites quivalentes au FMS ; et une autre solution gratuite : le PHP via le protocole HTTP. Nous verrons les deux sortes de communication possibles entre Flash et PHP : le passage linstanciation de lanimation, et le passage lors de lexcution de lanimation par requte. Ces deux types denvoi de donnes sont trs diffrents, autant dans leur utilisation que dans les mthodes employes. vous de voir en fonction de vos besoins dans vos applications.

pour rcuprer une page quelle va ensuite lire et analyser pour obtenir les informations contenues. Lavantage cette fois-ci est que lapplication peut insrer dans la requte des informations que le serveur recevra.

Passage linstanciation : les FlashVars

Lorsque vous insrez une animation Flash dans une page html, vous linsrez dans une certaine configuration que vous dfinissez. Pour cela vous passez un certain nombre de paramtres : le chemin du fichier swf que vous voulez afficher, la qualit des graphismes, la couleur de fond de lanimation, et ce qui nous intresse dans cet article : les FlashVars. Lenvoi de donnes par cette
Listing 1. Code HTML d'intgration d'une application Flash avec FlashVars
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8444553540000" codebase= HYPERLINK "http://fpdownload. macromedia.com/pub/shockwave/cabs/ash/swash.cab" \ l "version=8,0,0,0"http://fpdownload.macromedia.com/ pub/shockwave/cabs/ash/swash.cab#version=8,0,0,0 width="550" height="400" id="Sans nom-1" align="middle"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="exemple.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="ashvars" value="parametre1=valeur1&magazi ne=PHP%20Solution" /> <embed src="exemple.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="exemple" align="middle" allowScriptAccess= "sameDomain" ashvars="prenom=Jrme&nom=Forget" type="application/x-shockwave-ash" pluginspage="http:// www.macromedia.com/go/getashplayer" /> </object>

Comment ? Quand surtout !

Il y a deux manires pour envoyer des donnes une application Flash, et elles se distinguent principalement par le moment o vous voulez faire passer les informations. La premire mthode consiste envoyer les informations avant que lanimation soit lance : cest son instanciation que lapplication cliente va assimiler ces informations. Principal avantage de cette mthode : trs simple mettre en place. Principal dfaut: le flux dinformation est unidirectionnel : lapplication pourra recevoir les informations mais ne pourra pas en envoyer au serveur par ce biais. Dans la seconde mthode, lapplication Flash va envoyer une requte HTTP
36

8/2010

Flash et PHP

Listing 2. Exemple simple de fonction PHP pour l'utilisation des FlashVars


<?php $ashvars = ""; function ashvarsAdd($var, $value){ return urlencode($var)."=".urlencode($value)."&"; } $ashvars .= phpSolutions $ashvars .= $ashvars .= ?> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase=http://fpdownload.macromedia.com/pub/shockwave/ cabs/ash/swash.cab#version=8,0,0,0 width="550" height="400" id="Sans nom-1" align="middle"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="animation.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="ashvars" value="<?php echo $ashvars ?>" /> <embed src="animation.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="exemple" align="middle" allowScriptAccess="sameDomain" ashvars="<?php echo $ashvars; ?>" type="application/xshockwave-ash" pluginspage="http://www.macromedia.com/go/ getashplayer" /> </object> ashvarsAdd("question","Etes-vous lecteur de ?"); ashvarsAdd("labelVote1", "oui"); ashvarsAdd("labelVote2", "non");

return urlencode($var)."=".urlencode($value)."&";

$ ashvars .= ashvarsAdd("question","Etes-vous lecteur de phpSolutions ?"); $ ashvars .= ashvarsAdd("labelVote1", "oui"); $ ashvars .= ashvarsAdd("labelVote2", "non"); ?> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8444553540000" codebase=http://fpdownload.macromedia. com/pub/shockwave/cabs/ ash/sw ash.cab#version=8,0,0,0 width="550" height="400" id="Sans nom-1" align="middle"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="animation.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name=" ashvars" value="<?php echo $ ashvars ?>" /> <embed src="animation.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="exemple" align="middle" allowScriptAccess= "sameDomain" ashvars="<?php echo $ ashvars; ?>" type="application/x-shockwave- ash" pluginspage="http:// www.macromedia.com/go/get ashplayer" /> </object>

Listing 5. com.php, le script php qui va nous permettre le lien entre la bdd et l'application ash
<?php // Connexion BDD $ _ sqlHost = "localhost"; $ _ sqlUser = "root"; $ _ sqlPassword = ""; $ _ sqlDataBase = "phpSolution "; mysql _ connect($ _ sqlHost, $ _ sqlUser, $ _ sqlPassword); mysql _ selectdb($ _ sqlDataBase); // Fonction facilitant l'envoi d'informations function ashvarsAdd($var, $value){ return urlencode($var)."=".urlencode($value)."&"; } // L'id du vote est contenu dans idChoix, on incrmente donc le compteur pour ce vote mysql _ query("UPDATE sondage SET compte = compte + 1 WHERE 'idChoix' = ".$ _ REQUEST['idChoix']); // On afche les rsultats de faon lisible pour l'application Flash, // exemple de ce que va afcher ce bloc: choix1=9&choix2=7&total=16& $total = 0; $sqlRequest = mysql _ query("SELECT * FROM sondage WHERE 1;"); while($sqlResult=mysql _ fetch _ array($sqlRequest)){ echo ashvarsAdd("choix".$sqlResult['idChoix'], $sqlResult['compte']); $total += $sqlResult['compte']; } echo ashvarsAdd("total", $total); ?>

Listing 3. Utilisation de la classe LoadVars


<? var sender = new LoadVars(); var loader = new LoadVars(); //enregistrement des informations envoyer sender.nomParametre1 = "valeur1"; sender.nomParametre2 = "valeur2"; loader.onLoad = function(success) { if (success) { //afchage des donnes reues trace(this.nomReponse1); trace(this.nomReponse2); else{ }; } } trace("la requte a chou");

sender.sendAndLoad("com.php",loader,"POST");

Listing 4. index.php, a chage de l'application Flash


<?php $ ashvars = ""; function ashvarsAdd($var, $value){

mthode se fait travers un paramtre appel FlashVars et ayant pour valeur une chane de caractre contenant toutes les donnes que vous souhaitez faire passer. Cette chane est une combinaison de paramtre=valeur spars par des &, les caractres spciaux et dchappements tant cods sous la forme %+2 caractres hexadcimaux (pour faire simple, il sagit de lencodage que lon retrouve pour lenvoi de donnes dun formulaire html une autre page par mthode GET aussi appewww.phpsolmag.org

l url-encoding). Le Listing 1 vous prsente lensemble du code HTML permettant lintgration dune application flash avec passage de paramtres linstanciation. Comme vous pouvez le remarquer on rpte le passage des arguments au niveau du paramtre movie ainsi que dans la balise embed. Ceci est d au fait que les navigateurs ninterprtent pas tous le paramtre FlashVars de la mme faon. Par souci de compatibilit, il est donc conseill de procder ainsi.
37

Pratique

Enfin, pour envoyer des informations une application Flash par cette mthode, il suffira ct serveur dcrire une fonction gnrant dynamiquement les balises dintgration de lanimation munies du paramtre flashvars (cf Listing 2), et de lire ces paramtres travers des variables flash classiques de nom _root.nomParamtre.

Listing 6. Code AS2 de l'application Flash


// choixA et choixB sont les 2 instances des boutons qui permettront le vote choixA.texte = _ root.labelVote1; choixB.texte = _ root.labelVote2; choixA.onPress = function() { appelServeur(1); } choixB.onPress = function() { appelServeur(2); } // NB : le champs question visible sur la Figure 1 est un champs textuel dynamique ayant pour valeur _ root.question qui se trouve tre attribue directement par les ashvars, aucun code Actionscript n'est ncessaire pour ce champs. // resultatA et resultatB sont les deux barres traduisant les rsultats du vote, // non visible pour l'instant puisque l'utilisateur n'a pas encore vot. resultatA. _ visible = false; resultatB. _ visible = false; function appelServeur(choix:Number){ var sender = new LoadVars(); var loader = new LoadVars(); choisi // on prpare l'envoi l'id du vote qui a t sender.idChoix = choix;

Passage pendant lexcution

Dans ce genre dchange, cest lanimation qui va tre linitiatrice de la requte. Lchange dinformation se fera comme ceci : le client (lanimation Flash) envoie une requte contenant les donnes que lon souhaite faire parvenir au serveur. Le serveur (script php) analyse la requte et en dgage une rponse sous forme de page HTML. Enfin le client reoit la rponse sa requte contenant les informations transmises par le serveur. Pour envoyer et recevoir les informations, Flash a mis disposition des bibliothques rendant la cration et lanalyse des requtes totalement transparentes.

Du cot Actionscript

En AS2, cest la classe LoadVars qui va nous permettre de communiquer avec un serveur distant, et ce de faon totalement transparente : son utilisation est montre dans le Listing 3. Avec cette classe, lenvoi et la rception de donnes se font trs simplement au travers dinstances, et on peut distinguer deux types dinstances (pour lenvoi et la rception) cres partir du mme constructeur. Pour tablir un change dinformation avec un serveur, vous devrez tout dabord crer deux instances : une servant pour lenvoi et une servant pour la rception. Celle servant pour lenvoi doit contenir les donnes que vous souhaitez transmettre au serveur. Pour cela vous naurez qu lui appliquer des proprits portant le nom des paramtres : instanceEnvoi.nomParametre = valeur. Une fois toutes vos proprits dfinies, vous naurez qu appeler la mthode sendAndLoad de cette instance dans laquelle vous spcifierez linstance grant le retour des donnes, ladresse du script CGI auquel vous souhaitez transmettre les informations, et enfin la mthode avec laquelle vous souhaitez envoyer ces informations (POST ou GET). Comme vous laurez compris, pour grer lanalyse des donnes reues, vous devrez crer une deuxime instance. La contrainte principale de cette deuxime instance est quelle doit dfinir une mthode portant un nom bien spcifique, qui sera appele une fois que les informations seront reues. Cette mthode portant le nom onLoad contiendra toutes les donnes reues qui sont stockes dans les proprits de cette instance. Vous pourrez donc les obtenir lintrieur de la mthode par this.nomParamtre. Cette mthode reoit comme paramtre une variable boolenne dterminant si la requte bien t envoye puis reue correctement. Nous lavons appel sucess, elle peut tre fausse si par exemple le fichier ou ladresse na pas
38

loader.onLoad = function(success) { if (success) { //on donne aux barres des dimensions proportionnelles aux votes reus _ root.resultatA. _ height = Math.round(300*this.choix1/this.total); _ root.resultatB. _ height = Math.round(300*this.choix2/this.total); } else{ trace("la requete a chou"); } }; // on envoi les informations sender.sendAndLoad("com.php",loader,"POST"); // on desactive les boutons et on afche les barres (toujours invisible puisque hauteur nulle) choixA. _ visible = false; choixA.enabled = false; choixB. _ visible = false; choixB.enabled = false; resultatA. _ visible = true; resultatB. _ visible = true; };

t trouv. NB : pour faciliter le debuging dune application flash, vous pouvez galement dans la mthode onLoad rcuprer lensemble de la rponse contenu dans this.toString().

Du cot PHP

Afin que lapplication flash puisse interprter correctement les informations, les donnes envoyes par le serveur, il faut quelles soient mises sous la forme urlencoding. Pour cela il existe une fonction en php portant le mme nom : urlencode. Cette fonction retourne la chane de caractre passe en paramtre en chane de caractre encode sous la forme url-encoding.
8/2010

Flash et PHP
Figure 1. Dans lditeur Flash

Application, nonc du problme

Pour mettre en application tout ce que nous venons de voir, nous allons prendre un exemple simple. Imaginons que nous voulions faire une application Flash permettant de crer des sondages ( choix binaire dans notre cas) la vole. Posons comme cahier des charges que les intituls de la question et des rponses possibles soient paramtrables et que lapplication puisse rpondre deux besoins : rpondre la question pose et voir sous forme dune animation Flash le rsultat global du sondage. Dans ce cas les deux types dchange de donnes seront utiliss. Nous emploierons le passage linstanciation pour paramtrer linterface, cest--dire dfinir les intituls, et nous favoriserons le passage pendant lexcution pour envoyer la rponse du sond et rcuprer les rsultats globaux, avant de les utiliser pour les afficher dans linterface.

Figure 2. Avant que lutilisateur ne clique sur un des boutons

Figure 1. Dans lditeur Flash

Choix technologiques

Vu le cahier des charges que nous nous sommes impos, quel que soit le contexte dans lequel lanimation Flash tournera, le libell des questions et des rponses possibles restera le mme. Dans ce cas, la communication des libells des questions est unidirectionnelle ; nous utiliserons donc les FlashVars. Ensuite, une fois que lutilisateur aura fait son choix pour le sondage, lanimation Flash devra lenvoyer au serveur pour que le choix soit comptabilis au sein de la base de donnes. Il faudra donc utiliser la classe LoadVars. Nous profiterons galement de cet envoi pour rcuprer les rsultats globaux du sondage et les afficher sous forme danimation. Un des procd les plus simples et les plus efficaces graphiquement est la reprsentation sous forme de btons : pour chaque choix on prend un carr de couleur uniforme diffrente et on lui donne une hauteur reprsentant le rapport des Figure 3. Affichage du rsultat voix quil a remport. Vous trouverez lensemble du code ainsi que les explications en commentaires dans les listings 4, 5 et 6, ainsi que des illustrations dans les figures 1,2 et 3

Figure 2. Avant que lutilisateur ne clique sur un des boutons

Conclusion

Maintenant vous savez faire communiquer une application Flash et un serveur php. Vous allez pouvoir enrichir vos interfaces. Nombreuses sont les applications qui soffrent vous : envoi de mail, processus didentification, rendu graphique de donnes Rappelons enfin que 98% des clients internet actuels possdent le plugin permettant de lire les fameux fichiers .swf. Lancez vous !

JRME MANCHON
Jrme Manchon poursuit actuellement des tudes dingnieur lENSAM tout en menant en parallle des projets personnels a n dlargir et approfondir ses connaissances dans le milieu du PHP et de la programmation. Jerome.manchon@gmail.com
39

Figure 3. A chage du rsultat www.phpsolmag.org

Fiche technique

Usages avancs

des sessions avec la POO


Aujourd'hui, la grande majorit des sites dynamiques crits en PHP utilisent le mcanisme natif des sessions. Dans certaines situations, ce moyen de stockage des sessions n'est pas le plus appropri et peut se voir remplac par un moteur de stockage diffrent, une base de donnes par exemple.
Cet article explique :
Comment manipuler les sessions sous forme dobjets PHP. Comment dplacer le stockage des sessions vers une base de donnes MySQL.

Ce quil faut savoir :


Comment fonctionne le mcanisme des sessions PHP. Avoir des bases de programmation oriente objet.

objectif de ce cours consiste dans un premier temps dvelopper une approche oriente objet des sessions natives de PHP afin de simplifier leur utilisation. Puis nous chercherons tendre ce mcanisme en vue de stocker les sessions dans une base de donnes MySQL sans avoir modifier lAPI principale en profondeur. Veuillez noter cependant que cet article ne couvre pas les bases du systme natif des sessions. Le numro du mois de juin 2010 de ce magazine ddie un article complet ce sujet et nous ne pouvons que vous inviter le lire attentivement avant de vous plonger dans les prochaines lignes.

Rappels sur les sessions PHP

Le mcanisme des sessions PHP a t instaur dans le langage dans le but de proposer un moyen de persister des informations entre les requtes HTTP. En effet, le protocole HTTP est sans tat (stateless) et fonctionne en mode non connect. Cela signifie que deux requtes HTTP successives mises depuis la mme adresse IP sont compltement indpendantes lune de lautre. La reconnaissance de lutilisateur entre deux requtes HTTP est ralise au moyen dun cookie de session contenant un jeton unique didentification. Selon la configuration de PHP (session.use_cookies, session.use_only_cookies et session.use_trans_ id), lidentifiant de session peut galement tre pro-

pag par lintermdiaire dune variable complmentaire dans lurl (GET).


www.phpsolmag.org

En terme dAPI, PHP fournit une vingtaine de fonctions (http://fr.php.net/manual/en/ref.session.php) utiles la configuration et la manipulation des sessions. A cette liste de fonctions sajoute le tableau superglobal $_SESSION charg daccueillir les donnes de session. Ce tableau est accessible en lecture et en criture. Il est automatiquement initialis au dmarrage du script. Le Listing 1, page1.php, donne un exemple dusage simple de lAPI des sessions. La premire ligne appelle la fonction session_name() avec le paramtre phpsolutions qui fixe le nom de la session, et donc du cookie de session. Par dfaut, le nom de la session est fix avec la valeur PHPSESSID. Ensuite, la fonction session_start() dmarre (ou restaure) la session courante tandis que la ligne suivante, session_regenerate_id(), force PHP recrer un nouvel identifiant de session afin dviter une ventuelle fixation de la session. Enfin la dernire ligne dclare une variable de session persistante, color, dans le tableau $_SESSION et linitialise avec la valeur blue. Le Listing 2, page2.php, ralise les mmes oprations que le morceau de code de la page 1. La diffrence se situe la dernire ligne qui lit la valeur de la variable de session color et laffiche sur la sortie standard. Bien sr, les trois premires lignes communes aux deux fichiers devraient tre mutualises dans un fichier spar ou dans une fonction utilisateur afin dviter la duplication du code. La plupart des dveloppeurs PHP interrompent leur usage des sessions PHP ces quelques lignes de code.
39

Sessions avec POO

Listing 1. Dmarrage dune session et criture dune variable de session


<?php session _ name('phpsolutions'); session _ start(); session _ regenerate _ id(); $ _ SESSION['color'] = 'blue';

session _ cache _ expire($this->options['session _ cache _ expire']); } if ($this->useCookies) { session _ set _ cookie _ params( $this->options['session _ cookie _ lifetime'], $this->options['session _ cookie _ path'], $this->options['session _ cookie _ domain'], $this->options['session _ cookie _ secure'], $this->options['session _ cookie _ httponly'] ); } if ($this->options['session _ auto _ start'] && !self::$isStarted) { session _ start(); session _ regenerate _ id(); self::$isStarted = true; } } } public function destroy() { $destroyed = session _ destroy(); if ($destroyed) { if ($this->useCookies) { setcookie($this->name, '', time() - 42000, $this->options['session _ cookie _ path'], $this->options['session _ cookie _ domain'], $this->options['session _ cookie _ secure'], $this->options['session _ cookie _ httponly'] ); } } } $this->clear();

Listing 2. Restauration dune session et lecture dune variable de session


<?php session _ name('phpsolutions'); session _ start(); session _ regenerate _ id(); echo $ _ SESSION['color'];

Listing 3. D nition de la classe SessionStorage


<?php class SessionStorage { static protected $isStarted = false; protected $name; protected $useCookies = true; protected $options = array(); public function _ _ construct($name, array $options = array()) { $this->name = $name; $this->useCookies = (boolean) ini _ get('session.use _ cookies'); $cookie = session _ get _ cookie _ params(); $this->options = array _ merge(array( 'session _ auto _ start' => true, 'session _ cache _ limiter' => 'nocache', 'session _ cache _ expire' => 180, 'session _ save _ path' => null, 'session _ id' => null, 'session _ cookie _ lifetime' => $cookie['lifetime'], 'session _ cookie _ path' => $cookie['path'], 'session _ cookie _ domain' => $cookie['domain'], 'session _ cookie _ secure' => $cookie['secure'], 'session _ cookie _ httponly' => isset($cookie['httponl y']) ? $cookie['httponly'] : false ), $options); if (!ini _ get('session.auto _ start')) { session _ name($this->name); if ($this->options['session _ id']) { session _ id($this->options['session _ id']); } if ($this->options['session _ save _ path']) { session _ save _ path($this->options['session _ save _ path']); } if ($this->options['session _ cache _ limiter']) { session _ cache _ limiter($this->options['session _ cache _ limiter']); } if ('nocache' !== $this->options['session _ cache _ limiter'] && $this->options['session _ cache _ expire'])

return $destroyed;

public function write($key, $value) { $ _ SESSION[$key] = $value; } public function read($key) { return array _ key _ exists($key, $ _ SESSION) ? $ _ SESSION[$key] : null; } public function remove($key) { if (null !== $value = $this->read($key)) { unset($ _ SESSION[$key]); } } } return $value;

Listing 4. Code de con guration de lhte virtuel Apache


<VirtualHost *:80> ServerName www.phpsolutions.local DocumentRoot "/Users/Hugo/Developpment/PHPSolutions/www" DirectoryIndex index.php <Directory "/Users/Hugo/Developpment/PHPSolutions/www"> AllowOverride All Allow from All </Directory> </VirtualHost>

40

8/2010

Fiche technique

Listing 5. Ligne ajouter au chier hosts de la machine


127.0.0.1 www.phpsolutions.local

Listing 6. Code principal du chier www/index.php


<?php // listing 6 require _ _ DIR _ _ . ' / ../src/SessionStorage.php'; function isValidColor($color) { return in _ array($color, array( 'rouge', 'vert', 'bleu', 'violet', 'orange', 'noir' ));

En effet, comment sassurer que le code fonctionne bien ? Comment assurer sa rutilisation dans un autre projet ? Comment dplacer le stockage des sessions vers un autre systme comme une base de donnes relationnelle ? Pour rpondre toutes ces questions, il convient de transformer lapproche procdurale du code en approche oriente objet. En somme, il sagit de percevoir la session comme un objet mtier PHP sur lequel sappliquent des actions. Lobjectif de la seconde partie de ce cours consiste dvelopper une classe PHP reprsentant une session PHP. Celle-ci encapsulera les actions ncessaires la configuration de la session, la lecture de variable ainsi que la fixation de variable.

$session = new SessionStorage('phpsolmag', array( 'session _ save _ path' => _ _ DIR _ _ . ' / ../tmp' )); $color = lter _ input(INPUT _ POST, 'color'); if (isValidColor($color)) { $session->write('favorite _ color', $color); header('Location: http://www.phpsolutions.local/index. php'); exit; } $color = $session->read('favorite _ color'); ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Bienvenue</title> </head> <body> <form action="index.php" method="post"> <eldset> <legend>Personnalisation</legend> <div> <label for="color">Couleur favorite</label> <select id="color" name="color"> <option value="rouge">Rouge</option> <option value="vert">Vert</option> <option value="bleu">Bleu</option> <option value="violet">Violet</option> <option value="orange">Orange</option> </select> <button type="submit">Ok</button> </div> </eldset> </form> <?php if (!$color) : ?> <p> Vous n'avez pas encore choisi de couleur. </p> <?php else: ?> <p> Votre couleur favorite est le <strong><?php echo $color ?></strong>. </p> <?php endif ?> </body> </html>

Vers une approche oriente objet

Comme son nom lindique, lapproche oriente objet ncessite de faire appel des objets. Par dfinition, on dit quun objet est une instance dune classe. Dit autrement, une classe est une sorte de moule partir duquel sont issus des objets. Il sagit donc de crer une classe SessionStorage charge dencapsuler la dfinition de la session courante. Une session se dfinit galement par un jeu de proprits et dactions. Les proprits sont les attributs dun objet, cest--dire les variables internes de lobjet. La classe SessionStorage, prsente au Listing 3, accueille trois proprits :
$name, une chane contenant le nom de la session $useCookies, une valeur boolenne indiquant si la

(ex: phpsolutions),

session courante transmet lidentiant de session par un cookie, $options, un tableau doptions de conguration de la session. La classe SessionStorage du Listing 3 encapsule galement un certains nombre de mthodes rpondant chacune un besoin particulier. Les paragraphes qui suivent prsentent une une ces mthodes. Notez que le code de la classe SessionStorage est largement inspir de celui du framework Open Source Symfony. La premire mthode, __construct(), est le constructeur de la classe. Elle a pour double rle de construire lobjet lappel du mot-cl new, mais surtout dinitialiser ce dernier. Dans le cadre de notre session, le constructeur ralise synthtiquement les trois tapes suivantes :

Ces dernires font le travail quon leur demande et le font bien. Nanmoins, cette approche procdurale du code peut savrer contraignante lorsque lapplication se compose de plusieurs centaines de fichiers et des milliers de lignes de code.
www.phpsolmag.org

I. Congurer le nom de la session. II. Congurer la session en fonction des valeurs transmises dans le tableau doptions pass en second paramtre. III. Dmarrer ou restaurer la session.
41

Sessions avec POO

La mthode read(), comme son nom lindique, sert lire une variable de session depuis le tableau $_SESSION. La fonction array_key_exists() sassure ici que le nom de la variable de session passe en paramtre de la mthode read() se trouve bien dans le tableau. Le test est important afin dviter de lever un avertissement au cas o lon essaierait datteindre un index inexistant dans le tableau $_SESSION. Lcriture de nouvelles valeurs dans la session est dlgu la mthode write() qui accepte deux paramtres : le nom de la variable de session et sa valeur. La mthode remove() offre la possibilit de supprimer une variable de session en lui passant en paramtre le nom de cette dernire. Enfin, la mthode destroy() a la responsabilit de dtruire la session. Cette mthode ne se limite pas seulement lappel de la fonction session_destroy(). En effet, elle vrifie galement si lidentifiant de session est propag par un cookie. Si cest le cas, un cookie vide et expir est envoy au navigateur.

Listing 7. Cration dune base de donnes depuis un client MySQL en ligne de commande
$ mysql -u root -p $ Enter password: Welcome to the MySQL monitor. Commands end with ; or \ g. Your MySQL connection id is 9 Server version: 5.1.49 Source distribution Copyright (c) 2000, 2010, Oracle and/or its afliates. All rights reserved. This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL v2 license Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>create databse php _ solutions;

Listing 8. Code SQL de cration de la table php_session


DROP TABLE IF EXISTS 'php _ session'; CREATE TABLE 'php _ session' ( 'id' integer(11) NOT NULL AUTO _ INCREMENT, 'sess _ id' varchar(50) NOT NULL UNIQUE, 'sess _ data' text NOT NULL, 'sess _ time' integer(14) UNSIGNED NOT NULL, PRIMARY KEY ('id') ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Mise en pratique

A prsent la classe SessionStorage est prte. Il convient de la tester laide dun petit exemple pratique. Il sagit dune application web compose dune page web, index.php, divise en deux parties : un formulaire et un paragraphe de texte. Le formulaire demande lutilisateur de choisir sa couleur favorite tandis que le paragraphe se charge dafficher cette dernire. Commenons tout dabord par crer un dossier PHPSolutions/ sur la machine. Celui-ci contiendra la structure initiale de lapplication dcrite ci-dessous : Le dossier src/ accueille la classe SessionStorage. Le dossier tmp/ stocke les chiers des sessions. Ce dossier doit donc tre accessible en lecture comme en criture par PHP. Le dossier www/ abrite les tous chiers accessibles depuis un navigateur web comme le script principal index.php.

Une fois larchitecture de lapplication en place, il faut configurer le serveur web Apache afin dempcher laccs aux dossiers src/ et tmp/ depuis un navigateur web. En rsum, il sagit de dfinir le dossier www/ comme tant la racine web du projet. Cest une bonne pratique de dveloppement web de sparer les fichiers accessibles publiquement de ceux qui ne doivent pas ltre. Ne rendez publiques que les fichiers que vous souhaitez atteindre depuis votre navigateur web. Tous les autres doivent tre placs au niveau suprieur afin de les protger des utilisateurs mal intentionns. Pour y parvenir, il suffit de dfinir un nouvel hte virtuel (virtual host) dans le fichier de configuration httpd. conf dApache. Dans les versions rcentes dApache, il sagit du fichier httpd-vhosts.conf dont linclusion est
42

parfois mise en commentaire la fin du fichier httpd. conf. Le Listing 4 prsente le code de lhte virtuel placer la fin du fichier httpd.conf avant de redmarrer le serveur Apache. Les chemins absolus de lhte virtuel sont bien videmment remplacer par ceux quivalents au systme hbergeant lapplication. La directive ServerName dfinit le nom de domaine utiliser pour atteindre le fichier index.php du rpertoire www/. Les directives AllowOverride et Allow from all indiquent respectivement que la configuration Apache du rpertoire www/ peut tre surcharge laide dun fichier .htaccess et que ce dossier est accessible par tout le monde. Le domaine www.phpsolutions.local est un domaine local, cest dire quil pointe sur ladresse IP locale 127.0.0.1. Il faut donc indiquer la machine comment rsoudre ce nom de domaine localement. Pour ce faire, il suffit dajouter la ligne du listing 5 au fichier hosts. Ce fichier se trouve dans le dossier /etc sur les environnements Linux et dans C:\Windows\System32\drivers\etc sur les plateformes Microsoft. Enfin, le Listing 6 donne le code du fichier www/ index.php. Ce fichier se compose de deux parties : le code PHP qui traite la requte utilisateur et la session, puis le code HTML destin laffichage des donnes. La premire ligne de ce fichier inclut la dfinition de la classe SessionStorage afin de pouvoir linstancier quelques lignes plus bas. Le bloc de lignes suivantes dclare une fonction utilisateur isValidColor()
8/2010

Fiche technique

Listing 9. D nition de la classe MySQLSessionStorage


<?php require _ _ DIR _ _ .'/SessionStorage.php'; class MySQLSessionStorage extends SessionStorage { protected $dbh; public function _ _ construct($name, PDO $dbh, array $options = array()) { $this->dbh = $dbh; // Table that stores session data $options = array _ merge(array( 'db _ table' => 'php _ session', 'db _ id _ col' => 'sess _ id', 'db _ data _ col' => 'sess _ data', 'db _ time _ col' => 'sess _ time' ), $options); $options['session _ auto _ start'] = false; parent:: _ _ construct($name, $options); // Ask PHP to use this class to handle sessions instead of // its native behavior session _ set _ save _ handler( array($this, 'sessionOpen'), array($this, 'sessionClose'), array($this, 'sessionRead'), array($this, 'sessionWrite'), array($this, 'sessionDestroy'), array($this, 'sessionGC') ); } session _ start();

// delete the record associated with this id $sql = 'DELETE FROM ' .$db _ table.' WHERE ' .$db _ time _ col.' < ' .(time() - $lifetime); try { $this->dbh->query($sql); } catch (PDOException $e) { throw new Exception(sprintf('Unable to clean expired sessions. Message: %s', $e->getMessage())); } } return true;

public function sessionRead($id) { // get table/columns $db _ table = $this->options['db _ table']; $db _ data _ col = $this->options['db _ data _ col']; $db _ id _ col = $this->options['db _ id _ col']; $db _ time _ col = $this->options['db _ time _ col']; try { $sql = 'SELECT ' .$db _ data _ col.' FROM ' .$db _ table.' WHERE ' .$db _ id _ col.'=?'; $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR, 255); $stmt->execute(); $sessionRows = $stmt->fetchAll(PDO::FETCH _ NUM); if (1 === count($sessionRows)) { return $sessionRows[0][0]; } else { // session does not exist, create it $sql = 'INSERT INTO ' .$db _ table.'(' .$db _ id _ col.', ' .$db _ data _ col.', ' .$db _ time _ col.') VALUES (?, ?, ?)'; $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR); $stmt->bindValue(2, '', PDO::PARAM _ STR); $stmt->bindValue(3, time(), PDO::PARAM _ INT); $stmt->execute(); } return '';

public function sessionClose() { return true; } public function sessionOpen($path = null, $name = null) { return true; } public function sessionDestroy($id) { // get table/column $db _ table = $this->options['db _ table']; $db _ id _ col = $this->options['db _ id _ col']; // delete the record associated with this id $sql = 'DELETE FROM ' .$db _ table.' WHERE ' .$db _ id _ col.'= ?'; try { $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR); $stmt->execute(); } catch (PDOException $e) { throw new Exception(sprintf('Unable to destroy the session. Message: %s', $e->getMessage())); } } return true;

} catch (PDOException $e) { throw new Exception(sprintf('Unable to read session data. Message: %s', $e->getMessage())); } } public function sessionWrite($id, $data) { // get table/column $db _ table = $this->options['db _ table']; $db _ data _ col = $this->options['db _ data _ col']; $db _ id _ col = $this->options['db _ id _ col']; $db _ time _ col = $this->options['db _ time _ col']; $sql = 'UPDATE '.$db _ table.' SET ' .$db _ data _ col.' = ?, ' .$db _ time _ col.' = ' .time().' WHERE ' .$db _ id _ col.'= ?'; try { $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $data, PDO::PARAM _ STR); $stmt->bindParam(2, $id, PDO::PARAM _ STR); $stmt->execute(); } catch (PDOException $e)

public function sessionGC($lifetime) { // get table/column $db _ table = $this->options['db _ table']; $db _ time _ col = $this->options['db _ time _ col'];

www.phpsolmag.org

43

Sessions avec POO

Listing 9. D nition de la classe MySQLSessionStorage suite


throw new Exception(sprintf('Unable to write session data. Message: %s', $e->getMessage())); } } return true; {

Listing 10. Code principal du chier www/index.php (version 2)


<?php require _ _ DIR _ _ .'/../src/MySQLSessionStorage.php'; function isValidColor($color) { return in _ array($color, array( 'rouge', 'vert', 'bleu', 'violet', 'orange', 'noir' ));

// Ask PHP to use this class to handle sessions instead of // its native behavior session _ set _ save _ handler( array($this, 'sessionOpen'), array($this, 'sessionClose'), array($this, 'sessionRead'), array($this, 'sessionWrite'), array($this, 'sessionDestroy'), array($this, 'sessionGC') ); } session _ start();

public function sessionClose() { return true; } public function sessionOpen($path = null, $name = null) { return true; } public function sessionDestroy($id) { // get table/column $db _ table = $this->options['db _ table']; $db _ id _ col = $this->options['db _ id _ col']; // delete the record associated with this id $sql = 'DELETE FROM ' .$db _ table.' WHERE ' .$db _ id _ col.'= ?'; try { $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR); $stmt->execute(); } catch (PDOException $e) { throw new Exception(sprintf('Unable to destroy the session. Message: %s', $e->getMessage())); } } return true;

$dbh = null; try { $dbh = new PDO( 'mysql:dbname=php _ solutions;host=127.0.0.1', 'root', '', array(PDO::MYSQL _ ATTR _ INIT _ COMMAND => "SET NAMES 'UTF8'") ); $dbh->setAttribute(PDO::ATTR _ ERRMODE, PDO::ERRMODE _ EXCEPTION); } catch (PDOException $e) { echo 'Unable to connect to MySQL:<br/>'; echo $e->getMessage(); die; } $session = new MySQLSessionStorage('phpsolmag', $dbh); $color = lter _ input(INPUT _ POST, 'color'); if (isValidColor($color)) { $session->write('favorite _ color', $color); header('Location: http://www.phpsolutions.local/index. php'); exit; } ?> <!-- suite du code ... --> require _ _ DIR _ _ .'/SessionStorage.php'; class MySQLSessionStorage extends SessionStorage { protected $dbh; public function _ _ construct($name, PDO $dbh, array $options = array()) { $this->dbh = $dbh; // Table that stores session data $options = array _ merge(array( 'db _ table' => 'php _ session', 'db _ id _ col' => 'sess _ id', 'db _ data _ col' => 'sess _ data', 'db _ time _ col' => 'sess _ time' ), $options); $options['session _ auto _ start'] = false; parent:: _ _ construct($name, $options);

public function sessionGC($lifetime) { // get table/column $db _ table = $this->options['db _ table']; $db _ time _ col = $this->options['db _ time _ col']; // delete the record associated with this id $sql = 'DELETE FROM ' .$db _ table.' WHERE ' .$db _ time _ col.' < ' .(time() - $lifetime); try { $this->dbh->query($sql); } catch (PDOException $e) { throw new Exception(sprintf('Unable to clean expired sessions. Message: %s', $e->getMessage())); } } return true;

public function sessionRead($id) { // get table/columns $db _ table = $this->options['db _ table']; $db _ data _ col = $this->options['db _ data _ col']; $db _ id _ col = $this->options['db _ id _ col']; $db _ time _ col = $this->options['db _ time _ col']; try

44

8/2010

Fiche technique

Listing 10. Code principal du chier www/index.php (version 2) suite


$sql = 'SELECT ' .$db _ data _ col.' FROM ' .$db _ table.' WHERE ' .$db _ id _ col.'=?'; $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR, 255); $stmt->execute(); $sessionRows = $stmt->fetchAll(PDO::FETCH _ NUM); if (1 === count($sessionRows)) { return $sessionRows[0][0]; } else { // session does not exist, create it $sql = 'INSERT INTO ' .$db _ table.'(' .$db _ id _ col.', ' .$db _ data _ col.', ' .$db _ time _ col.') VALUES (?, ?, ?)'; $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $id, PDO::PARAM _ STR); $stmt->bindValue(2, '', PDO::PARAM _ STR); $stmt->bindValue(3, time(), PDO::PARAM _ INT); $stmt->execute(); } return ''; {

} catch (PDOException $e) { throw new Exception(sprintf('Unable to read session data. Message: %s', $e->getMessage())); } } public function sessionWrite($id, $data) { // get table/column $db _ table = $this->options['db _ table']; $db _ data _ col = $this->options['db _ data _ col']; $db _ id _ col = $this->options['db _ id _ col']; $db _ time _ col = $this->options['db _ time _ col']; $sql = 'UPDATE '.$db _ table.' SET ' .$db _ data _ col.' = ?, ' .$db _ time _ col.' = ' .time().' WHERE ' .$db _ id _ col.'= ?'; try { $stmt = $this->dbh->prepare($sql); $stmt->bindParam(1, $data, PDO::PARAM _ STR); $stmt->bindParam(2, $id, PDO::PARAM _ STR); $stmt->execute(); } catch (PDOException $e) { throw new Exception(sprintf('Unable to write session data. Message: %s', $e->getMessage())); } } return true;

qui a pour rle de sassurer que la valeur passe en paramtre est une couleur attendue parmi la liste de valeurs possibles. A partir de la ligne 9, la classe de session est instancie afin de produire un objet $session dont le nom du cookie de session est phpsolmag. Loption session_ save_path quant elle dfinit le dossier dans lequel les fichiers des sessions seront crites. Ici, il sagit du rpertoire tmp/ de notre application.
www.phpsolmag.org

Ensuite, la fonction filter_input() rcupre la valeur de la variable $_POST[color] issue du formulaire. Si aucune valeur na t transmise, alors la variable $color contiendra la valeur null par dfaut. Puis, le dernier bloc conditionnel sassure que la valeur de la couleur transmise en PHP est valide. Si cest le cas, on fait appel la session pour y stocker la valeur de la couleur dans la variable de session favorite_ color. Une redirection est ensuite dclenche laide de la fonction header(). Enfin, la dernire ligne du bloc de code PHP tente de rcuprer la valeur de la variable de session favorite_ color. Si la valeur existe alors elle est affiche dans la partie HTML, sinon un message demande lutilisateur de bien vouloir choisir sa couleur prfre parmi la slection propose. Pour tester lapplication, il suffit de se rendre dans un navigateur et de saisir lurl http://www.phpsolutions. local. La Figure 1 montre lapplication sa premire excution tandis que la seconde affiche le rsultat aprs avoir choisi la couleur bleu dans la liste droulante. Le rpertoire tmp/ contient prsent les fichiers de session dont le nom contient lidentifiant de session transmis dans le cookie. Cette petite application prouve le fonctionnement de lobjet SessionStorage. Le mcanisme des sessions a t entirement rcrit laide dune classe PHP. Mise part la syntaxe oriente objet, cette nouvelle manire de percevoir la session sous forme dun objet mtier apporte de nombreux avantages. Le premier avantage est sans aucun doute la rutilisabilit du code. En effet, il suffit de copier le fichier SessionStorage.php dans les diffrents projets afin de bnficier de cette nouvelle API plus verbeuse et plus facile dutilisation. Dautre part, grce la programmation oriente objet, le code est dsormais compltement testable grce aux tests unitaires. Il aurait ainsi t possible dcrire une srie de tests unitaires dans PHPUnit pour sassurer que les objets SessionStorage se comportent bien comme on sy attend. Enfin, limplmentation technique (le tableau $_SESSION et toutes les fonctions session_*()) a t entirement masque par une API de plus haut niveau grce la classe et ses mthodes. Par consquent, tous les comportements implments ici peuvent tre redfinis ou surchargs et cest dailleurs tout le sujet de la partie suivante. En effet, il sagira de translater le stockage des sessions vers une base de donnes MySQL sans ncessiter une importante mise jour du code de lapplication.

Etendre le mcanisme des sessions

Aujourdhui, les dveloppeurs web doivent faire face de plus en plus de contraintes lorsquils travaillent pour un client. Ils doivent en effet prendre en compte lexistant de ce dernier. De plus, avec la professionnalisation
45

Sessions avec POO

Figure 1. A linitialisation de lapplication

Figure 2. Aprs enregistrement dune variable de session

et lindustrialisation des dveloppements web, il nest plus rare davoir intgrer une application web dans un environnement technique existant et parfois trs contraignant. Il convient donc dadopter des stratgies au niveau du code source pour sassurer que ce dernier sadaptera lui mme lenvironnement technique. Par exemple, crire une application capable de se connecter une base de donnes MySQL ou PostGreSQL sans avoir toucher tout le reste du code. Contraintes et limites des sessions natives Le combat est aussi le mme pour les sessions. Dans la majorit des cas, le mcanisme natif de gestion des sessions de PHP suffit lui mme car lapplication web fonctionne sur un seul serveur web. Cependant, la donne change si lon est amen installer une seconde machine LAMP capable dabsorber une partie de la charge. Imaginons simplement un rpartiteur de charge qui redirige arbitrairement la premire requte de lutilisateur sur le premier serveur car ce moment l, il est moins
46

sollicit. La session de lutilisateur est alors ouverte et le fichier de session sauvegard sur le serveur 1. La seconde requte est dclenche mais elle est cette fois-ci redirige sur le serveur 2. Comment ce dernier peut-il rcuprer les donnes de session alors quelles se trouvent sur le premier serveur ? Cest embtant... Une solution simple consiste monter un systme de fichier de partage et de configurer la constante de PHP session.save_path des deux serveurs afin quelle pointe dans ce dernier. A partir des contraintes souleves, il semble tout fait judicieux de raliser un systme capable dadapter le stockage des sessions sans ncessiter de grosse intervention sur le code source de lapplication. Pour y parvenir, la meilleure solution consiste tendre et redfinir le comportement original des sessions afin de stocker les sessions dans une base de donnes MySQL. Prparer la base de donnes Avant de sattaquer au code, il convient tout dabord de crer une nouvelle base de donnes php_solutions.
8/2010

Fiche technique

Listing 11. Contenu de la table php_session linitialisation de lapplication


mysql> select id, sess _ id, sess _ data, sess _ time from php _ session; +----+----------------------------+-----------+------------+ | id | sess _ id | sess _ data | sess _ time | +----+----------------------------+-----------+------------+ | 1 | ljn1sbiuhr481829qk4jfcfoh0 | | 1282167188 | +----+----------------------------+-----------+------------+ 1 row in set (0.01 sec)

Listing 12. Contenu de la table php_session aprs enregistrement dune variable de session
mysql> select id, sess _ id, sess _ data from php _ session; +----+----------------------------+----------------------------+ | id | sess _ id | sess _ data +----+----------------------------+----------------------------+ | 1 | ljn1sbiuhr481829qk4jfcfoh0 | favorite _ color|s:4:"vert"; | +----+----------------------------+----------------------------+ 1 row in set (0.00 sec)

Cette tche peut tre accomplie dans un gestionnaire de base de donnes MySQL graphique comme PHPMyAdmin ou bien MySQL Query Browser. Vous pouvez galement utiliser la ligne de commande MySQL comme le montre le Listing 7. Maintenant que la base de donnes est cre, ltape suivante consiste crer la table php_session destine accueillir les donnes de session. Cette table est constitue de quatre champs : id, sess_id, sess_data et sess_time. Le Listing 8 donne en langage SQL la dfinition complte de la table. Cest ce code que vous devez excuter dans votre gestionnaire de base de donnes afin de crer physiquement la table dans la base de donnes. Le champ id constitue la cl primaire de la table. Sa valeur est auto incrmente et gre par le moteur MySQL. La colonne sess_id est une chane de longueur variable (varchar) stockant lidentifiant de session. La valeur est obligatoire et doit tre unique dans toute la table. Le champ sess_data est une chane multiligne accueillant la chane srialise des donnes de session. Enfin, le champ sess_time est un entier non sign obligatoire stockant la valeur de la dernire date de mise jour des donnes de session sous la forme dun timestamp Unix. La base de donnes est prte recevoir les nouvelles sessions grce la classe MySQLSessionStorage dvoile dans la partie suivante. La classe MySQLSessionStorage Lobjectif prsent consiste dvelopper un nouvel adaptateur capable de translater le mcanisme natif des sessions vers une base de donnes MySQL. Pour y parvenir, il convient de raliser une nouvelle classe MySQLSessionStorage qui tend la classe SessionStorage et redfinit les comportements natifs. Le listing 9 prsente lintgralit de cette classe. La nouvelle classe MySQLSessionStorage accueille prsent un constructeur et six nouvelles mthodes:
sessionClose(), sessionOpen(), sessionGC(), sessionRead(), sessionWrite() et sessionDeswww.phpsolmag.org

troy(). Le constructeur accepte une instance de PDO

en argument et configure diverses options de la session. Les six mthodes restantes sont appeles automatiquement par le gestionnaire des sessions PHP avant et aprs lexcution du script. Cest la fonction session_set_save_handler() de PHP qui est responsable de redfinir tous les comportements internes du gestionnaire de session. Le gestionnaire de sessions LAPI des sessions de PHP offre une manire simple et intelligente de redfinir entirement les mcanismes internes de gestion des sessions. La fonction session_ set_save_handler() (http://fr.php.net/session-set-save-handler) remplit parfaitement ce besoin. La documentation officielle indique que cette fonction accepte six paramtres obligatoires. Chacun de ces arguments est une fonction utilisateur de rappel ou bien un tableau contenant une instance et le nom de la mthode publique correspondante appeler. On parle alors de callable. Le premier paramtre dfinit la fonction douverture de la session. Cette fonction reoit toujours deux paramtres : le chemin vers le dossier de stockage des sessions ainsi que le nom de la session. Ici, cest la mthode sessionOpen() qui est configure. Elle renvoie toujours true. Le second paramtre dfinit la fonction de fermeture de la session. Cette fonction agit comme un destructeur de classe, et est excute lorsque le script se termine. Dans la classe MySQLSessionStorage, cest la mthode sessionClose() qui sera appele. Elle renvoie toujours true. Le troisime paramtre de la fonction session_set_ save_handler() configure la fonction de lecture de la session. La fonction configure accepte lidentifiant de session comme paramtre et doit tre obligatoirement une chane contenant les donnes de session. Il sagit dune chane srialise servant initialiser le tableau de session $_SESSION au dmarrage de la session. Si
47

Sessions avec POO

aucune donne de session nexiste, alors la chane retourne doit tre vide. La mthode sessionRead() tente tout dabord de rcuprer la session en cours depuis la table php_session grce une requte SQL SELECT intgrant lidentifiant de session pass en paramtre. Sil existe un enregistrement, alors la mthode retourne le contenu de la colonne sess_data qui correspond la chane srialise. Si aucun tuple (ligne) nest rapatri, alors la mthode initialise une session en base de donnes en crant un nouvel enregistrement dans la table. Remarquez ici lutilisation de PDO et des requtes prpares afin dviter tout risque dinjection SQL. Le quatrime paramtre permet de dfinir la fonction de rappel appele au moment de la sauvegarde des donnes de session. Cette fonction est appele par PHP aprs lexcution du script et reoit deux paramtres : lidentifiant de session ainsi que la chane srialise du tableau de session. Ici, cest la mthode sessionWrite() qui se charge de remplir ce besoin. Cette dernire met jour lenregistrement correspondant la session dans la table php_session laide dune requte SQL UPDATE. Le cinquime paramtre de la fonction session_ set_save_handler() dfinit ensuite la fonction de destruction de la session. Cette fonction accepte lidentifiant de session en paramtre. Le comportement de destruction est automatiquement excut lorsque la fonction session_destroy() est invoque. Dans notre exemple, la mthode sessionDestroy() sera appele lorsque la mthode destroy() de lobjet de session est appele. La mthode sessionDestroy() dtruit la session en supprimant lenregistrement correspondant dans la table php_session. Enfin, le dernier paramtre dfinit la fonction de nettoyage des sessions expires. Cette dernire accepte un unique paramtre qui est la dure de vie maximale dune session, exprime en secondes. La mthode sessionGC() de la classe MySQLSessionStorage se charge de supprimer de la table php_session tous les enregistrements dont la valeur de la colonne sess_time correspond une date expire. La prochaine et dernire partie de cet article sarticule autour des tests de cette nouvelle classe avec notre prcdente application. Test de la classe MySQLSessionStorage La dernire tape de ce cours avanc sur les sessions consiste tester la nouvelle classe MySQLSessionStorage avec notre prcdente application. Pour y parvenir, il convient de modifier les premires lignes du fichier index.php comme le montre le Listing 10. Le bloc try { } catch { } ouvre une connexion sur la base de donnes MySQL php_solutions en instanciant un objet PDO. Le nom dutilisateur MySQL est ici root et le mot de passe est vide. En cas derreur, une exception
48

de type PDOException est intercepte et interrompt le cours normal du script. Si la connexion sur la base de donnes est valide, alors la classe MySQLSessionStorage est instancie. Le reste du code de lapplication reste exactement le mme que prcdemment. Les Listings 11 et 12 prouvent respectivement le fonctionnement de lapplication. A louverture de la page www.phpsolutions.local, une nouvelle session est enregistre en base de donnes avec lidentifiant ljn1sbiuhr481829qk4jfcfoh0. Comme aucune couleur na t slectionne, il nexiste pas encore de donne de session dans la colonne sess_data. Lenvoi du formulaire avec vert comme valeur de couleur favorite entrane la mise jour de la session dans la base de donnes. La colonne sess_data se voit attribuer la valeur prsente dans le Listing 12.

Conclusion

Cet article a t loccasion de dcouvrir des usages avancs du mcanisme des sessions de PHP en sappuyant sur une approche oriente objet. Cette dernire apporte un certain nombre de bienfaits au code source de lapplication. En effet, le code de lapplication est prsent plus facile utiliser, maintenir et faire voluer. De plus, le code crit ici est prsent entirement testable laide dun framework de tests unitaires comme PHPUnit mais il est aussi et surtout rutilisable. Enfin, le code sadapte tout aussi aisment un gestionnaire de session diffrent. Par consquent, il sera dsormais possible de basculer au choix sur des sessions natives ou bien vers une base de donnes MySQL. En se basant sur les exemples prsents et grce aux concepts de la programmation oriente objet (hritage, implmentation dinterfaces, classes abstraites...), il convient de crer de nouvelles classes capables dadapter de nouveaux gestionnaires de session. En effet, la cration des adaptateurs pour dautres bases de donnes relationnelles (SQLite, PostGreSQL, Oracle...) devient trivial. Bien entendu, il ne sagit pas que de se limiter ces systmes. Un stockage en mmoire vive avec Memcache ou bien dans des bases NoSQL (CouchDB, MongoDB, Cassandra...) sont des alternatives compltement envisageables.

HUGO HAMON
Hugo Hamon est responsable des formations chez Sensio Labs et passionn de dveloppement web. Il est lorigine du site Apprendre-PHP.com et coauteur dun ouvrage sur le framework Symfony aux ditions Eyrolles. Sur son temps libre, Hugo Hamon participe lAFUP en tant que Secrtaire Gnral et publie des billets sur son blog http://www.hugohamon.com. 8/2010

Pour les dbutants

Les applications
WEB 2.0
Web 2.0 est un terme la mode parmi lensemble des sites internet. Dans cet article, nous tudierons le sens de ce terme ainsi que quelques applications Web qui vhiculent cette ide.

Cet article explique :


Les principes des applications Web 2.0. Des exemples d'applications Web 2.0.

Ce quil faut savoir :


Connatre une partie des sites les plus connus du web (Google, Wikipdia, Facebook...). Connatre les principaux langages du web : HTML, CSS, PHP, Ajax serait un plus.

e web regorge de sites quon nomme parfois applications Web 2.0. Au travers de son histoire, le web a volu pour aboutir limage quon connat de lui aujourdhui. Dans cet article nous verrons dans un premier temps ce quest le Web 2.0 puis nous illustrerons cette notion au travers de diffrentes applications plus ou moins clbres.

CGI sont sorties telles que FastCgi. CGI fut donc lune des premires solutions (si ce nest pas la premire) permettre un lien entre un client et un serveur.

Une tincelle : cot Serveur

Au commencement....

A ses dbuts, le web consistait en une srie de pages html (HyperText Markup Language) contenant du texte, des images ainsi que des liens permettant daccder dautres pages contenant des lments du mme type. Le web tait purement statique, pas de formulaire permettant une inscription ou poster des commentaires. Il ntait donc pas possible dinteragir avec les sites tel quon le fait aujourdhui en sinscrivant, connectant, uploadant un fichier, postant un commentaire pour ragir une news etc. Il ny avait donc aucune interactivit possible.

Une premire : CGI

Apparue ds les premiers pas du World Wide Web en 1993, CGI (pour Common Gateway interface) est une interface qui, au lieu denvoyer un fichier (page, image...) permet dexcuter un programme et retournera le rsultat gnr. CGI permet de passer des arguments au programme afin de modifier le rsultat gnr, pour un programme de recherche par exemple. Cependant, une certaine lourdeur est apparue et dautres solutions ont vues le jour depuis. Ainsi des version amliores de
50

Rasmus Lerdorf cra en 1994 une bibliothque logicielle en Perl pour son site web afin de pouvoir mmoriser qui avait visit son CV. Plus le temps passait et plus il ajoutait de nouvelles fonctionnalits tant et si bien quil se dcida r-implmenter ses fonctions en langage C capables de discuter avec une base de donnes. Lensemble des fonctions cres prenaient alors pour nom PHP/FI (pour Personal Home Page Tools/Form Interpreter). En 1998, le langage sortit dans une version 3 dveloppe par 2 tudiants : Andi Gutmans et Zeev Suraski. Peu de temps aprs, une version 4 est apparue et le langage prit le nom de PHP : Hypertext Preprocessor. Avec cette nouvelle version, un modle de dveloppement t introduit dans le dveloppement de sites web : le modle Objet. Mme si la conception implmente dans cette version 4 a fait dbat sur vrai objet ou pas. La version 5 de PHP a permit de reprendre une grande partie des principales notions de la programmation oriente objet. Vous connaissez srement les volutions suivantes ainsi que le succs rencontr par ce langage.

Une tincelle : cot client

Au cours de lanne 2001, Microsoft implmenta lobjet XmlHttp en tant quobjet ActivX. Mozilla ajouta lobjet sous le nom XMLHttpRequest peu de temps
8/2010

Web 2.0

aprs dans son clbre navigateur Firefox. Pour simplifier, lorsquon navigue sur un mme site, on recharge toute la page ce qui inclut le design de la page : fichier CSS, images, fichiers Javascript, texte se retrouvant sur toutes les pages du site comme le menu... Cela nest plus vrai aujourdhui dans le sens ou les navigateurs ont implment un cache qui permet de stocker les fichiers CSS, les images et dautres donnes. Cependant le contenu texte, contenu dans le code html, sera re-tlcharg. Cela impose donc une utilisation parfois superflue de la bande passante. La nouveaut que permet lobjet XMLhttp/XMLHttpRequest cest simplement de recharger une partie de la page. Par exemple considrons 3 cases de type text dans un formulaire et un bouton submit. En tapant du texte dans les 2 premires puis en cliquant sur le bouton envoyer, une requte contenant les valeurs contenues dans les 2 premiers champs texte sera envoye au serveur et, suite un traitement, ce dernier enverra sa rponse. Lobjet pourra enfin insrer cette rponse dans la page du navigateur client sans avoir recharger lensemble de la page mais seulement la partie formulaire. Cet exemple, bien que ralisable en javascript pur (concatnation de 2 chanes ), dmontre ici lutilisation possible de la solution Ajax. Grce cette solution, il est possible de concevoir des pages web qui ne se rechargent pas ou seulement en partie.

Rejoignez le Club .PRO Rejoignez le Club .PRO


Stonfield Inworld : editor@phpsolmag.org Pour plus de renseignement
de dveloppement. Au-del de ses services, la socit consacre 30% de ses ressources des travaux de R&D sur le e-Commerce et le e-Learning dans les Mondes Virtuels Conseil, conception et dveloppement d'applications volues pour les systmes d'informations Internet/intranet/extranet. Alliant les COGNIX comptences Systems d'une SSII et d'une Web Agency, Cognix Systems conoit des applicatifs et portails web 'ergonomie travaille veloppement volues pour Conseil, conception et d d'lapplications et des sites Internet forte valeur ajoute. les syst mes d'informations Internet/intranet/extranet. Alliant les http://www.cognix-systems.com comptences d'une SSII et d'une Web Agency, Cognix Systems

Pour plus de renseignement : editor@phpsolmag.org

Stonfield Inworld propose aux entreprises des solutions globale d'intgration d'Internet et des Univers Virtuels dans leur stratgie Stonfield Inworld de dveloppement. Au-del de ses services, la socit consacre 30% de ses ressources des travaux de R&D des sur le e-Commerce Stonfield Inworld propose aux entreprises solutions globale le e-Learning dans les Mondes Virtuels det 'int gration d'Internet et des Univers Virtuels dans leur stratgie

COGNIX Systems

Rejoignez le Club .PRO


de Gestion de la Relation Client (CRM), d'ecommerce et de travail COGNIX Systems
Conseil, conception et dveloppement dapplications volues pour les systmes dinformations Internet/ ollaboratif. intranet/extranet. Alliant les comptences dune SSII et dune Web Agency, Cognix Systems conoit des http://www. core-techs. fr applicatifs et portails web lergonomie travaille et des sites Internet forte valeur ajoute. PoP Factory,SSII spcialise Web. Dveloppement de solutions http://www.cognix-systems.com

et employant les dernieres technologies du web (PHP5, MySQL5, Ajax, XHTML, CSS2). Core-Techs http://www.web82.net Pour plus de degestion renseignement : editor@phpsolmag.org Expert des solutions et de communication d'entreprise en Open Source, Core-Techs conoit, integre, dploie et maintient des StoneldCore-Techs Inworldde Gestion de Contenu Web, de Gestion Documentaire, systemes Stoneld Inworld propose aux entreprises des solutions globale dintgration dInternet et des Univers de Gestion de la Relation Clientet (CRM), d'ecommerce et de travail Virtuels dans leur stratgie dveloppement. Au-del de ses services, la socit consacre 30% de Expert desde solutions de gestion de communication d'entreprise ses ressources des travaux de R&D sur le e-Commerce et le e-Learning dans les Mondes Virtuels. ollaboratif. en Open Source, Core-Techs conoit, integre, dploie et maintient des http://www. fr systemes de core-techs. Gestion de Contenu Web, de Gestion Documentaire,

conoit des applicatifs et portails web l'ergonomie travaille et des sites Internet forte valeur ajoute. WEB82 http://www.cognix-systems.com bergements Cration et h bergements de de sites sites web web pour pour particuliers, particuliers, associations, associations, entreprises, e-commerce. Dveloppement Dveloppement entierement aux normes WEB82 qualit, au graphisme soign W3C (www.w3.org) de sites web de qualit, soign etemployant les dernieres technologies du web (PHP5, associations, MySQL5, bergements Cr ation et h bergements de de sites sites web web pour pour particuliers, particuliers, associations, Ajax, XHTML, CSS2). D entreprises, e-commerce. Dveloppement veloppement entierement aux normes http://www.web82.net qualit, au graphisme soign W3C (www.w3.org) de sites web de qualit, soign

Un terme

POP FACTORY

Cest en 2003 que lexpression Web 2.0 apparue. Elle dsigne des sites reposant sur un ensemble de donnes plus ou moins fournies par les utilisateurs (administrateurs ou personnes inscrites), un effet de rseau (pas forcment social) invitant la participation (Soyez le premier donner votre avis), proposant parfois des systmes de syndication (flux rss) ainsi que des web services. Dun point de vue technologique, cela aboutit principalement lutilisation dun site web dynamique utilisant bien entendu de lHtml et du Css mlangs assez souvent du JavaScript voire de lAjax pour un rsultat encore plus dynamique ainsi quun langage dynamique cot serveur tel que PHP. Pour rsumer, on pourrait dire quun site Web 2.0 est un site reposant assez souvent sur les donnes fournies par les utilisateurs que lon invite participer activement de telle manire quil est plac au centre du systme.

Anaska Formation Nous accompagnons nos clients tout au long de leur projet : audit,

Anaska est le spcialiste des formations les technologies OpenSource. En partenariat avec MySQL PoP Factory,SSII spsur de solutions cialis e Web. D veloppement AB, Mandriva, Zend et d'autres acteurs de la communaut, Anaska vous propose un catalogue de plus conseil, dveloppement, applicatives spcifi ques ; suivi offre et degestion. solutions packages : catalogue de 50 formations ddis aux technologies du Libre. http://www.popfactory.com / info@popfactory.fr numrique, e-commerce, livre/magazine numrique, envoi SMS. http://www.anaska.com

POP FACTORY numrique, e-commerce, livre/magazine numrique, envoi SMS.

applicatives spcifi ques ; offre de solutions packages : catalogue

Nous accompagnons nos clients tout au long de leur projet : audit, conseil, dveloppement, suivi et gestion. Blue Note Systems http://www.popfactory.com / info@popfactory.fr Cration et hbergements de sites web pour particuliers, associations, entreprises, e-commerce. Dveloppement Sp entierement aux normes (www.w3.org) sites web de qualit, graphisme cialistes en CRMW3C Open Source, de nous proposons uneau offre soign et employant les dernieres technologies du web (PHP5, MySQL5, Ajax, XHTML, CSS2). complte de prestations sur la solution SugarCRM. Notre valeur http://www.web82.net Blue Systems ajoute Note rside dans une expertise ractive et une exprience des problmatiques de laOpen GRC.Source, Nous vous aidons tirer une le meilleur Spcialistes en CRM nous proposons offre Core-Techs parti de votre solution CRM. compl tegestion de prestations sur la solution SugarCRM. valeur Expert des solutions de et de communication dentreprise en Open Notre Source, Core-Techs http://www.bluenote-systems. com conoit, integre, dploierside et maintient deractive Gestion et de une Contenu Web, de des Gestion ajoute dans des unesystemes expertise exprience

WEB82

Documentaire, de Gestion de la Relation Client (CRM), decommerce et de travail ollaboratif. problmatiques de la GRC. Nous vous aidons tirer le meilleur http://www.core-techs.fr

parti de votre solution CRM. Intelligence Power http://www.bluenote-systems. com POP FACTORY Conseil, Expertises, Formations et Projets E-business centrs au tour PoP Factory,SSII spcialise Web. Dveloppement de solutions applicatives spciques ; offre de du cur de mtier : la Business Intelligence. Power solutions packages : catalogue numrique, e-commerce, livre/magazineIntelligence numrique, envoi SMS. vous Nous accompagnonsIntelligence nos clients tout au long dePower leur projet : audit, conseil, dveloppement, suivi et gestion. propose des solutions innovant.es pour aligner la technologie sur http://www.popfactory.com / info@popfactory.fr la stratgie de votreFormations entreprise. et Projets E-business centrs au tour Conseil, Expertises, http://www. intelligencepower. du cur de mtier : la Business com Intelligence. Intelligence Power vous

Blue Note Systems propose des solutions innovant.es pour aligner la technologie sur

Quelques applications !

Spcialistes en CRM Open Source, nous proposons une offre complte de prestations sur la la stratgie de votre entreprise. solution SugarCRM. Notre valeur ajoute rside dans une expertise ractive et une exprience des problmatiqueshttp://www. de la GRC. Nous vous aidons tirer lecom meilleur parti de votre solution CRM. intelligencepower. http://www.bluenote-systems.com

Aujourdhui le rseau internet dispose de milliards de machines proposant parfois un site web. Certains dentre eux noffrent que la dcouverte dune passion ralis par un particulier. Dautres, raliss par des entreprises, proposent du contenu parfois trs diffrent ! On parle parfois dapplications. Nous allons en tudier quelques une par catgories.
www.phpsolmag.org

Vous souhaitez tre en premire page des moteurs de recherche ? Intelligence Power Rejoignez-nous, 100% des clients Web Alliance sont en 1re page Conseil, Expertises, Formations et Projets E-business centrs au tour du cur de mtier : la Business de Google. Web Alliance, socit de conseil spcialise dans le Web Alliance Intelligence. Intelligence Power vous propose des solutions innovantes pour aligner la technologie sur rfrencement internet, vouspropose son moteurs expertisede (rfrencement, la stratgie de votre entreprise. Vous souhaitez tre en premi re page des recherche ? http://www.intelligencepower.com liens sponsoriss, web-marketing). Rejoignez-nous, 100% des clients Web Alliance sont en 1re page www. web-alliance. fr de Google. Web Alliance, socit de conseil spcialise dans le

Web Alliance

Web Alliance rfrencement internet, vous propose son expertise (rfrencement,

Vous souhaitez tre en premire page des moteurs de recherche ? Rejoignez-nous, 100% des clients liens web-marketing). Web Alliance sont ensponsoriss, 1re page de Google. Web Alliance, socit de conseil spcialise dans le rfrencement internet, vous propose sonfr expertise (rfrencement, liens sponsoriss, web-marketing). www. web-alliance. www.web-alliance.fr

Club .PRO
51

Pour les dbutants

Forums

Le style dapplication le plus rpandu sur le net est bien entendu les forums qui permettent chaque inscrit de poster un sujet aussi appel topic sur lequel les autres utilisateurs pourront rpondre pour rpondre la question poste par le premier utilisateur ou fournir des informations complmentaires. Parmi les services les plus utiliss en France nous retrouverons forumactif.fr et xooit.com/fr/. Toujours pour les fans du je fais moi mme, ces deux services reposent sur les forums PHPBB : forums.phpbb-fr.com. Ce dernier site est la rfrence francophone du support phpBB et non son site officiel que lon peut trouver www.phpbb. com.

Autres applications clbres

Blogs

Les blogs pourraient tre eux aussi un des principaux styles dapplications les plus rpandus sur le net. Aujourdhui, ils en sont mme devenus incontournables. Beaucoup dinternautes disposent dun blog parfois personnel ou professionnel. Un blog, cest un site ou le propritaire peut y poster un billet pour y exprimer une ide, parfois passagre mais aussi pour ragir sur lactualit ou simplement poster des photos damis, de vacances etc. Les autres utilisateurs inscrits sur le blog peuvent ragir leur tour en commentant le billet post. Pour crer un blog, il existe des services trs connus tels quover-blog.com, skyblog, hautetfort.com ou encore le service de Google blogger.com. Ces services proposent dhberger eux mme votre blog sur leur plate-forme et de le mettre jour dun point de vue technologique. Mais il est aussi possible pour les informaticiens en herbe de crer son propre blog, cod partir de zro ou pour plus de rapidit avec des CMS tels que Dotclear, Worldpress ou encore Drupal.

Il existe bien dautres applications trs connues : Google Maps permet de retrouver un lieu gographique en donnant comme indication une adresse ou des mots cls. Goportail permet lui aussi dexplorer la terre vue du ciel, du moins seulement le territoire franais. Il existe bien dautres applications clbres permettant la ralisation de document en ligne, de se crer un rseau social avec Facebook et compagnie, de crer des sites web sans connaissances informatique avec des CMS (Content Management System) tels que Joomla! Dailleurs Facebook est un exemple des possibilits offertes par PHP coupl ajax. Cependant, d une certaine lourdeur cre par le nombre dutilisateurs, facebook a dvelopp HipHop, qui permet de compiler les scripts PHP afin dobtenir une version plus rapide qui fonctionne avec PHP 5.2.

Le principe mash up

Partage multimdia

Outre le dsir de vouloir partager une ide, il est aussi possible de partager une vido, un son ou plus simplement des images. Parmi les plus clbre nous donnerons FlickR http://www.flickr.com pour le partage de photos, puis Youtube (youtube.com) et Dailymotion (dailymotion.com) pour le partage de vidos.

Lors de la relecture de cet article, on ma signal que javais omis un sujet pourtant interessant : les mash up. Mme si lon ne peut pas tout traiter au sein de cette article, le systme de mashs ups est lui aussi quasi incontournable. Pour ceux qui ne connaissent pas, prenons lexemple simple de la video filme dans la rue quon envoie sur Youtube. Une fois le video publie, Youtube met la disposition des visiteurs un code qui permet dinserer la video sur son propre blog ou site web. La possibilit du mash up est de permettre davoir sur un site du contenu qui nest pas hberg sur le dit site. Il existe beaucoup de solutions de ce genre. De plus beaucoup de sites mettent disposition des API permettant le dveloppement de nouvelles solutions grce une autre solution. LAPI qui doit tre vraisemblablement la plus utilise est celle de Google Maps. Un site peut alors proposer de naviger sur les cartes de google maps en y ajoutant des donnes supplmentaires.

Pour finir

Partage de connaissances

Parmi le top 10 des sites web les plus visits au monde, nous retrouverons bien videmment Wikipedia, http://fr.wikipedia.org reposant lui aussi sur la technologie PHP. Le but de wikipdia est le partage dinformations, de connaissances afin de raliser une grande encyclopdie en ligne qui peut tre remplie par tout le monde. Il existe sur le web diffrents sites reposant sur ce quon appelle des Wikis qui permettent tout utilisateur de contribuer la rdaction dinformations sur un domaine prcis comme le droit pour Jurispedia http:// fr.jurispedia.org/index.php/Accueil ou pas.
52

Lister lensemble des applications serait un travail ardu mais avec lensemble des sites web que nous venons daborder vous devez maintenant voir linteraction que doit permettre un site se disant Web 2.0. Le but principal est de fournir un service, de linformation et assez souvent, la possibilit de la complter, ou demander plus de prcision. On ne se limite plus un dictionnaire qui vous donne juste une dfinition mais aussi la possibilit de comprendre plus et den savoir encore plus.

NICOLAS TURMEAU
Nicolas Turmeau est un jeune tudiant en 3me anne de licence. Il utilise le langage PHP tous les jours depuis bientt deux ans. Il est le dveloppeur du jeu en ligne Numnor Online. Contact : nturmeau@iia-laval.fr. 8/2010

Web 2.0

www.phpsolmag.org

53

Pour les dbutants

54

8/2010

S-ar putea să vă placă și