Partager la session utilisateur entre Flash/Flex et symfony avec AmfPHP
Par NiKo le vendredi 25 juillet 2008, 17:07 - Dev
- Lien permanent -
3 commentaires -
Tags :
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 // 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 // ... $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) :
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 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 ?

3 commentaires (Ajouter un commentaire)
Très bonne nouvelle ce décorateur Flex
Je l'attend avec impatience !
Pour moi un gros avantage d'AMF, c'est les performances : http://ajaxian.com/archives/ria-dat...
Après, si on est pas trop regardant de ce côté là, on peut effectivement travailler avec des webservices Flex (SOAP/WSDL), voire avec une banale API REST en XML ou JSON.
Pour l'intégration avec symfony, l'idéal serait d'arriver à générer un format de sortie AMF depuis les vues, mais AmfPHP va poser beaucoup de problèmes à ce niveau là du fait de son architecture. Joshua May a tenté le coup avec son plugin sfAmfphpPlugin, mais c'est beaucoup de bidouille je trouve, d'où ma dernière question dans le billet concernant les alternatives existantes à AmfPHP... Je continue à creuser le sujet de toute façon, on a dans le pipe un décorateur Flex pour la future version de l'admin generator...
AmfPHP est vraiment puissant et facilite grandement le développement d'applications web avec une interface en Flash / Flex.
Par contre je m'interroge sur la pertinence de l'utiliser avec Symfony : leurs différences d'architecture ne risquent-elles pas de poser des problèmes à terme (incompatibilité futur entre les deux projets, maintenance, performances, ...) ?
Créer des vues qui génère du XML avec Symfony, qui seront analysées par l'application Flash/Flex me semble une solution plus robuste et pérenne : même si le trafic réseau augmente (protocole texte alors que AMF est pseudo-binaire), nous utilisons un format parfaitement supporté par Symfony comme AS3 et tout autre langage / brique logiciel moderne. Nous ne nous enfermons pas dans l'utilisation d'un protocole propriétaire relativement obscure et mal supporté.
Autre avantage à l'utilisation du XML : on peut très facilement générer une interface alternative au site (typiquement en HTML / CSS) afin de pouvoir référencer correctement le site et améliorer son accessibilité (lecteurs d'écrans, ...). J'ai présenté cette technique (grâce à XSLT et SWF Address) dans un billet il y-a quelques temps : http://lapin-blanc.net/27/05/2008/f...