Dans ce tutoriel, nous allons voir comment créer un module d'authentification en utilisant une base de données MySQL. Plusieurs principes seront abordés tout au loin de ce tutoriel. Nous verrons tout d'abord une utilisation simple du PopUpManager, nous verrons également la gestion des cookies avec l'objet SharedObject mais également comment intéragir avec un script coté serveur (dans notre cas PHP). Nous aborderons égalements les états (state) des composants pour permettre une modification de notre formulaire suite à une action de la part de l'utilisateur.

 

Le formulaire de connexion

Pour faciliter l'intégration, nous allons opter pour l'utilisation du PopUpManager.
De ce fait, nous pourrons afficher le formulaire quel que soit la
page sur laquelle nous nous trouvons.
 
Voici le composant mxml du formulaire (LoginForm.mxml) :
< ?xml version="1.0" encoding="utf-8"?>
< mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" title="Authentification">
    < mx:Form id="loginForm">
        < mx:FormItem label="Nom d'utilisateur">
            < mx:TextInput id="username"/>
        < /mx:FormItem>
        < mx:FormItem label="Mot de passe">
            < mx:TextInput id="password" displayAsPassword="true"/>
        < /mx:FormItem>
        < mx:ControlBar id="buttonBar" width="100%" horizontalAlign="center">
            < mx:Button id="submit" label="Connexion" click="onClick(event);"/>
        < /mx:ControlBar>
        < mx:FormItem id="remember">
            < mx:CheckBox id="rememberMe" label="Se souvenir de moi"/>
        < /mx:FormItem>
    < /mx:Form>
< /mx:TitleWindow>  

 

La classe User

La classe qui s'occupe de la connexion, déconnexion, ... de l'utilisateur :

package com {

    import mx.controls.Alert;

    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.URLRequest;
    import flash.net.URLLoader;
    import flash.net.URLVariables;
    import flash.net.URLRequestMethod;
   
    import com.SHA1;
    import com.UserEvent;

    public class User extends EventDispatcher {
       
        private var isLogged : Boolean;
        private var username : String;
       
        public function User():void {
            isLogged = false;
            username = "";
        }
       
        public function login(name:String, password:String):void {
            var chargeur : URLLoader = new URLLoader ();
            var mes_vars : URLVariables = new URLVariables();
            mes_vars.user = name;
            mes_vars.pass = SHA1.encrypt(password);
           
            username = name;
                   
            var adresse:URLRequest = new URLRequest("assets/php/index.php?action=connect");
            adresse.method = URLRequestMethod.POST;
            adresse.data = mes_vars;
   
            chargeur.addEventListener(Event.COMPLETE, endLoading);
            chargeur.load(adresse);
        }
       
        public function endLoading(e:Event):void {
            var contenu : XML = XML(e.target.data);
            if(contenu=="true") {
                dispatchEvent(new Event(UserEvent.AUTHENTICATE_SUCCESS));
                isLogged = true;
                Alert.show("Vous êtes maintenant connecté.", "Information");
            }else{
                username = "";
                dispatchEvent(new Event(UserEvent.AUTHENTICATE_FAIL));
                Alert.show("Erreur lors de la connection.", "Information");
            }
        }
       
        public function logout():void {
            isLogged = false;
            username = "";
            Alert.show("Vous êtes maintenant déconnecté.", "Information");
        }
       
    }

} 
Nous avons deux fonctions principales, la fonction de connexion, la fonction de déconnexion. 
La fonction login fait appel à une autre fonction endLoading pour traiter la réponse générée par le script PHP. Et bien évidemment, nous avons le constructeur de la classe qui permet d'initialiser nos attributs.
Pour gérer les évenements, nous avons également besoin d'une classe UserEvent :
package com {
    import flash.events.Event;
    import flash.events.EventDispatcher;

    public class UserEvent extends Event {
        public function UserEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false):void {
            super(type, bubbles, cancelable);
        }
   
        public static const AUTHENTICATE_SUCCESS:String = "success";
        public static const AUTHENTICATE_FAIL:String = "fail";
    }

} 

 

Le script PHP

Avant tout, nous avons besoin d'une table sql pour stocker les identifiants et mots de passe de nos utilisateurs.
CREATE TABLE IF NOT EXISTS `User` (
  `id` int(11) NOT NULL auto_increment,
  `pseudo` varchar(50) NOT NULL,
  `password` varchar(40) NOT NULL,
  PRIMARY KEY  (`id`)
)  
Pour faciliter le développement et éviter d'avoir trop de fichier, nous allons utiliser un seul fichier PHP mais lors de l'appel de celui-ci, nous lui passerons une variable "action" en GET.
Nous allons également utiliser la classe SQL suivante.
Voici la structure de notre script :
if(!isset($_GET['action']) || $_GET['action']=='') { die('aucune action specifiee'); }
require_once("assets/php/mysql.class.php");
$db_host = "localhost";
$db_username = "root";
$db_password = "";
$db_name = "MaTable";
$db_prefixe = "";
$db = new Mysql($db_host, $db_username, $db_password, $db_name, $db_password);
switch($_GET['action']) {
    default :
        echo 'false';
        break;
}
Maintenant que nous avons la structure de notre script, voyons plus en détail la récupération des données :
echo'';
if(!isset($_POST["user"]) || !isset($_POST["pass"])) {
    echo 'false';
}
else {
    $user = $_POST["user"];
    $pass = $_POST["pass"];
   
    $vari =  $db->select("*","User","pseudo='$user' AND password='$pass'","","");
    if($db->nbrecord($vari)!=0) echo 'true';
    else echo'false';
}
echo''; 
Nous récuperons les variables passer en POST par notre swf, nous faisons la requete, puis nous envoyons la réponse via du XML pour que celle-ci puisse être traitée par flash.
 

Sauvegarde de la connexion dans un cookie

Sur notre formulaire, nous avons positionné une checkbox qui permet de sauvegarder la connexion. Pour ce faire, nous aurons besoin de stocker notre connexion dans un cookie en utilisant la class SharedObject. Voici maintenant le composant principal de notre application :
< ?xml version="1.0" encoding="utf-8"?>
< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    backgroundGradientColors="[0x000000,0x323232]" color="#FFFFFF"
    initialize="initializeHandler(event)" >
   
    < mx:Script>
        < ![CDATA[
            import mx.containers.Form;
            import mx.controls.Alert;
            import mx.managers.PopUpManager;
           
            import com.User;
            import com.UserEvent;
            import views.LoginForm;

            private var loginForm:LoginForm; // notre formulaire
            private var user : User = new User(); // notre utilisateur
           
            private var sharedObject:SharedObject; // access au cookie
            private var chargeur : URLLoader;

            private function initializeHandler(event:Event):void{
               
                //récupère le sharedObject utilisé pour stocker les données
                sharedObject = SharedObject.getLocal("userData");

                // Ecoute les évenements de la class User
                user.addEventListener(UserEvent.AUTHENTICATE_SUCCESS, removeLoginForm);
                user.addEventListener(UserEvent.AUTHENTICATE_FAIL, displayLoginForm);

                // Si aucun cookie n'est trouvé, on affiche le formulaire de connexion
                if (sharedObject.data.user == null){
                    displayLoginForm();
                }
                else { // sinon on le connecte
                    user.login(sharedObject.data.user.username, sharedObject.data.user.password);
                }
            }

            private function displayLoginForm(event:Event = null):void{
                if(loginForm == null){
                    loginForm = new LoginForm();
                    loginForm.user = user;
                    PopUpManager.addPopUp(loginForm, this, true);
                    PopUpManager.centerPopUp(loginForm);
                }
            }

            private function removeLoginForm(event:Event = null):void{
                if(loginForm != null){
                    PopUpManager.removePopUp(loginForm);
                    loginForm = null;
                }
            }
           
            private function logout(e:Event):void {
                // on supprime l'instanciation du user
                user.logout();
                // on vide le cookie
                sharedObject.clear();
                initializeHandler(new Event(""));
            }
           
        ]]>
    < /mx:Script>
   
    < mx:Box>
        < mx:Label text="Vous etes maintenant connecté" />
        < mx:Button label="deconnect" click="logout(event)" />
    < /mx:Box>

< /mx:Application>
Lors de l'initialisation de notre application, nous regardons si un cookie est présent sur la machine de l'utilisateur. Si oui, nous le connectons. Sinon, nous affichons le formulaire de connexion.
La fonction displayLoginForm() affiche le formulaire dans un PopUp, alors que removeLoginForm() la retire de la display list.
 

Ajouter un formulaire d'inscription

Il serait interessant de pouvoir inviter l'utilisateur à s'inscrire sur votre application s'il ne l'est pas déjà. Nous allons donc ajouter un bouton qui va nous permettre de créer un champ supplémentaire pour confirmer le mot de passe et ainsi envoyer les données à notre script PHP qui pourra alors créer un tuple dans la table SQL si tout va bien.

Tout d'abord notre formulaire mis à jour. Nous allons utiliser les états pour permettre l'ajout de composant :

< mx:Form id="loginForm">
    < mx:FormItem label="Nom d'utilisateur">
        < mx:TextInput id="username"/>
    < /mx:FormItem>
    < mx:FormItem label="Mot de passe">
        < mx:TextInput id="password" displayAsPassword="true"/>
    < /mx:FormItem>
    < mx:ControlBar id="buttonBar" width="100%" horizontalAlign="center">
        < mx:LinkButton id="registerLink" label="S'inscrire ?" click="currentState='Register'"/>
        < mx:Button id="submit" label="Connexion" click="onClick(event);"/>
    < /mx:ControlBar>
    < mx:FormItem id="remember">
        < mx:CheckBox id="rememberMe" label="Se souvenir de moi"/>
    < /mx:FormItem>
< /mx:Form> 
Nous ajoutons simplement un bouton qui va nous permettre d'appeller un nouvel état lors d'un clique sur celui-ci. Voici les états :
< mx:states>
    < mx:State name="Register">       
        < mx:AddChild relativeTo="{buttonBar}" position="before">
            < mx:FormItem id="confirm" label="Confirmation">
                < mx:TextInput id="passConf" displayAsPassword="true"/>
            < /mx:FormItem>
        < /mx:AddChild>
           
        < mx:SetProperty target="{this}" name="title" value="Inscription"/>
        < mx:SetProperty target="{submit}" name="label" value="Inscription"/>
    
        < mx:RemoveChild target="{registerLink}"/>
        < mx:RemoveChild target="{remember}"/>
                   
        < mx:AddChild relativeTo="{submit}" position="before">
            < mx:target>
                < mx:LinkButton label="Retour" click="currentState=''"/>
            < /mx:target>
        < /mx:AddChild>
    < /mx:State>
< /mx:states> 
Nous n'avons besoin que d'un seul état, que nous nommerons Register.
Pour intéragir avec notre formulaire, nous avons besoins de trois composants mxml :
  • AddChild
  • RemoveChild
  • SetProperty
Le premier nous permet d'ajouter des éléments à notre display list, le deuxième de les enlever et le troisième permet de faire des modifications sur des composants déjà présent en le désignant grâce à l'attribut target, en précisant l'attribut qu'on souhaite modifier (name) puis en lui précisant la nouvelle valeur (value).

Nous avons maintenant besoin de modifier notre class User pour lui ajouter la fonction d'inscription, ainsi que celle qui va se charger de traiter la réponse de PHP :
public function subscribe(name:String, password:String):void {
    var chargeur:URLLoader = new URLLoader ();
    var mes_vars : URLVariables = new URLVariables();
    mes_vars.user = name;
    mes_vars.pass = SHA1.encrypt(password);
                   
    var adresse:URLRequest = new URLRequest("index.php?action=subscribe");
    adresse.method = URLRequestMethod.POST;
    adresse.data = mes_vars;
   
    chargeur.addEventListener(Event.COMPLETE, endSubscribe);
    chargeur.load(adresse);
}

private function endSubscribe(e:Event):void {
    var contenu : XML = XML(e.target.data);
    if(contenu=="true")
        Alert.show("Vous êtes maintenant enregistré.", "Information");
    else
        Alert.show("Erreur lors de l'inscription.", "Information");
} 
Et pour terminer, voici le script qui va insérer les données dans la table :
case 'subscribe':
    $user = $_POST['user'];
    $pass = $_POST['pass'];
    echo'';
    try {
        $up = $db->insert("VALUES('$user','$pass')","User (pseudo, password) ","");
        echo 'true';
    }
    catch (Exception $e) {
        echo 'false';
    }
    echo'';
    break; 

Pour terminer, voici un apercu de l'application finale :

Télécharger les sources.