Pour les besoins d'un projet récent, j'ai eu besoin de valider la possibilité de gérer l'authentification et l'accès à la session symfony (côté serveur) depuis une interface générée par Adobe Flex (en Flash, donc côté client).
Pour cela, j'ai utilisé la librairie AmfPHP en version 1.9beta2, certes pas très récente mais suffisament fonctionnelle pour satisfaire à ce besoin précis. Voyons comment ça se passe concrètement. L'avantage de la démonstration ci-dessous est qu'elle ne nécessite pas d'installer Flex puisque AmfPHP fournit un navigateur de services (browser) qui nous suffira pour valider notre concept.
Installation du plugin sfGuard
Je pars du principe que tout le monde a une installation de symfony 1.1 nanti d'une application main
, ainsi qu'un projet et un virtual host apache fonctionnels pointant sur local.mademo.org
. Si ce n'est pas le cas, voila de quoi vous mettre à jour.
On commence par installer le plugin sfGuard, qui se chargera de la persistance des droits et permissions utilisateurs en base de données, et fournira les utilitaires d'authentification et de manipulation de la session côté serveur :
$ ./symfony plugin:install sfGuardPlugin $ ./symfony propel-build-all $ ./symfony cc
On charge quelques données de test dans notre base de données nouvellement mise à jour :
$ mkdir data/fixtures $ cp plugins/sfGuardPlugin/data/fixtures.yml.sample data/fixtures/fixtures.yml $ ./symfony propel:data-load main
Ce jeu de données de test nous fournit par défaut un compte admin
(mot de passe admin
) qui nous servira à tester notre service d'authentification.
Ensuite, il nous faut modifier notre classe apps/main/lib/myUser.php
gérant la session utilisateur afin qu'elle étende désormais la classe sfGuardSecurityUser
, fournie par le plugin sfGuard :
php <?php // Fichier apps/main/lib/myUser.php class myUser extends sfGuardSecurityUser { }
Installation et configuration d'AmfPHP
Nous allons installer la librairie AmfPHP dans le sous-répertoire web/
de notre projet[1], et aménager quelque peu notre arborescence pour accueillir les services AmfPHP :
$ cd /path/to/project $ svn export https://amfphp.svn.sourceforge.net/svnroot/amfphp/tags/1.9beta2 web/amfphp $ mkdir lib/amfphp-services $ mv web/amfphp/services/amfphp lib/amfphp-services/
Ceci fait, nous allons éditer plusieurs fichiers d'amfphp afin de l'adapter à notre environnement symfony. Tout d'abord, commençons par éditer la valeur de la variable $servicesPath
dans le fichier web/amfphp/globals.php
:
php <?php // ... $servicesPath = dirname(__FILE__).'/../../lib/amfphp-services/';
Enfin, il nous faut "patcher"[2] le fichier web/amfphp/core/amf/app/Filters.php
, qui initialise la session PHP sans définir le nom de la session. Ici, nous utiliserons le nom de la session symfony par défaut, "symfony
" (ligne 105 du fichier) :
php 102 //Fix for godaddy not allowing ini_get 103 $sessionName = "PHPSESSID"; 104 } 105 session_name('symfony'); 106 session_start(); 107 $session_id = session_id();
Création d'un service permettant le partage de la session utilisateur
Voila, nous pouvons maintenant créer un service de gestion de l'authentification, que nous nommerons pompeusement UserSessionService
et que nous enregistrerons dans le fichier lib/amfphp-services/UserSessionService.php
:
php <?php require_once dirname(__FILE__).'/../../config/ProjectConfiguration.class.php'; /** * This class tests the symfony session within an AmfPHP context * */ class UserSessionService { /** * Symfony context * @var sfContext */ protected $context = null; /** * Symfony session * @var sfGuardSecurityUser */ protected $user = null; /** * Public constructor * */ public function __construct() { $configuration = ProjectConfiguration::getApplicationConfiguration('main', 'dev', true); $this->context = sfContext::createInstance($configuration); $this->user = $this->context->getUser(); } /** * Checks wheter user is authenticated or not * * @return boolean */ public function isAuthenticated() { return $this->getUser()->isAuthenticated(); } /** * Authenticates user * * @param string $username * @param string $password * @return boolean True if user has been successfully authenticated */ public function login($username, $password) { if ($this->isAuthenticated()) { return true; } $user = sfGuardUserPeer::retrieveByUsername($username); if (!is_null($user) && $user->checkPassword($password)) { $this->getUser()->signIn($user); return true; } return false; } /** * Signs out a user * */ public function logout() { return $this->getUser()->signOut(); } /** * Retrieves the current symfony context * * @return sfContext */ protected function getContext() { return $this->context; } /** * Retrieves the current symfony user session * * @return sfGuardSecurityUser */ protected function getUser() { return $this->user; } }
Pour tester notre service, utilisons le navigateur de service proposé par AmfPHP. Pour cela, il faut lancer un navigateur sur http://local.mademo.org/amfphp/browser/index.html
:
Via cette interface, elle même réalisée en Flex, on peut tester les méthodes publiques définies dans notre service, manipuler les arguments, et constater que nous arrivons à nous authentifier et que nous accédons bien à la même session utilisateur que dans symfony : login, logout et test du statut d'authentification.
En conclusion
On pourrait aller beaucoup plus loin dans cet exemple, en proposant par exemple une classe proxy en ActionScript 3 représentant un utilisateur du système (dans notre cas, une instance de la classe sfGuardUser
), cette dernière reproduisant tout ou partie de ses méthodes et propriétés, et donc d'utiliser l'ORM Propel directement depuis Flash... Je vous laisse faire vos tests si le coeur vous en dit.
D'autre part, même si la librairie AmfPHP semble un peu passée au niveau architecture, elle reste néanmoins très efficace pour publier des services PHP dans Flash au travers du protocole AMF. J'ai eu vent d'autres librairies comme WebORB ou SabreAMF, mais je ne sais pas vraiment ce qu'elles valent... Des avis dans l'assistance ?
Notes
[1] Du coup, on expose certains scripts AmfPHP, mais la librairie n'est malheureusement que prévue pour fonctionner en ce sens...
[2] Oui, c'est terriblement crade, je ne comprend d'ailleurs pas qu'AmfPHP n'aie pas prévu ce cas de figure...
Ce billet intitulé Partager la session utilisateur entre Flash/Flex et symfony avec AmfPHP a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.