Manipulation avancée des données

Feedback & authentification — Dépôt de fichiers

Licence Informatique, semestre 6

Alexandre Niveau — Valentin Lemière

Enseignement des technologies du Web

 

Manipulation avancée des données

Feedback & authentification — Dépôt de fichiers

Notes de cours

Travail personnel

Objectifs

Les deux premiers exercices sont des exercices d'application des principes de l'authentification et du dépôt de fichiers. Ils se veulent rapides et directs.

Les deux exercices suivants continuent à présenter l'architecture MVCR de manière incrémentale. Ils sont plus abstraits mais pas vraiment plus difficiles (bien que le quatrième soit vraiment moins guidé).

Exercice 1 — Bases de l’authentification

Une proposition de correction est disponible (archive du code).

Cette archive contient un fichier comptes.php, qui déclare simplement une liste de comptes utilisateur (nom, login, mot de passe, statut) sous forme de tableaux. Les mots de passe ont été hachés avec l'algorithme bcrypt, comme montré en cours. La liste contient quatre comptes ; le mot de passe de l'utilisateur toto est « toto », celui des trois autres est « 1234 ».

  1. Créer un script connexion.php qui inclut comptes.php, et qui affiche un message de bienvenue et un formulaire de connexion (login et mot de passe). La soumission du formulaire doit mener à la même page.
  2. Modifier le script pour qu'il analyse les données reçues. Si le login existe dans la base et que le mot de passe correspond, mettre le compte dans une variable de session, par exemple $_SESSION['user'].
  3. Modifier le script pour que le message de bienvenue soit personnalisé si la personne est connectée (par ex. « Bienvenue, Jean-Michel ! »).
  4. Faire en sorte que si la personne est connectée, ce ne soit pas un formulaire de connexion mais un formulaire de déconnexion qui soit affiché. Le traitement de la déconnexion est simple : la variable de session est supprimée. Vérifier que la connexion/déconnexion fonctionne correctement.
  5. Créer un script admin.php pour simuler une partie admin : la page doit afficher quelque chose comme « partie admin » si la personne est connectée et a le statut d'admin, et doit afficher un message d'erreur sinon. Tester les différents cas.

Exercice 2 (optionnel) — Dépôt de fichiers

Un corrigé de cet exercice est disponible (archive du code).

Créer un script affichant un formulaire permettant de déposer une image sur le serveur. Après le dépôt, la page devra montrer l'image déposée pendant toute la session de l'internaute.

Attention, chaque internaute devra avoir sa propre image : vous pouvez tester facilement en utilisant deux navigateurs différents. En particulier, que se passe-t-il si deux internautes déposent une image de même nom ?

Exercice 3 — Amélioration de l’ergonomie dans MVCR

Une proposition de correction incrémentale de ce TP est disponible ici sous forme d'un dépôt Git. Cet exercice commence au commit « Ajout d’un menu » et va jusqu'au commit « PRG+feedback pour suppression ». Une archive du résultat final (comprenant le dépôt) est disponible ici.

On continue le site sur les animaux fait aux deux TP précédents, en ajoutant les améliorations présentées en cours.

Avant de commencer cet exercice, il faut avoir avoir fait au moins toute la partie concernant la création d'un nouvel animal dans le TP précédent (c'est-à-dire jusqu'à « Suppression d'un animal » non compris).

Comme d'habitude, ne pas hésiter à s'inspirer de l'exemple des couleurs si vous avez des doutes, n'hésitez pas à jeter un œil à l'exemple des couleurs qui a été expliqué et complété en direct pendant le cours (résultat final, archive du code), mais évitez le copier-coller (mieux vaut réécrire, en essayant de comprendre ce qu'on écrit).

Ajout d'un menu

Si ce n'est déjà fait, ajouter un attribut $menu à la vue, qui contient une liste de couples URL-texte. Cette liste doit être utilisée dans le squelette pour afficher un menu en haut de la page.

Le menu doit contenir des liens vers la page d'accueil, la liste des animaux, et la page de création d'un animal.

POST-redirect-GET

Normalement, lors de la création d'un nouvel animal, le contrôleur appelle le makeAnimalPage de la vue. Comme vu en cours, ce n'est pas une bonne chose : on va plutôt demander au client de faire une nouvelle requête, en GET, vers la page de l'animal nouvellement créé.

  1. Ajouter une méthode POSTredirect($url) au routeur, qui envoie une réponse HTTP de type 303 See Other demandant au client de se rediriger vers l'URL passée en argument.
  2. Ajouter une méthode displayAnimalCreationSuccess($id) à la vue, qui redirige le client vers la page de l'animal dont l'identifiant est passé en paramètre. Dans le contrôleur, lorsqu'un nouvel animal a été correctement ajouté, appeler cette nouvelle méthode plutôt que makeAnimalPage.
  3. Tester. Vérifier notamment que l'actualisation de la page fonctionne correctement après ajout d'un nouvel animal.

Feedback

On voudrait donner un feedback à l'internaute, pour l'informer sur le résultat de ses actions (succès ou erreur).

  1. Ajouter un attribut $feedback à la vue, passé à son constructeur. Le squelette devra afficher le contenu de cet attribut quelque part en haut de la page.
  2. Modifier le routeur pour qu'il passe la chaîne "Test" comme feedback lorsqu'il construit la vue. Vérifier que ça fonctionne.
  3. À présent, on va passer comme feedback le contenu d'une variable de session $_SESSION['feedback']. Commencer une session au début du main du routeur, utiliser la variable de session pour construire la vue, puis supprimer le contenu de cette variable (le feedback n'est affiché qu'une seule fois).
  4. Modifier la méthode displayAnimalCreationSuccess de la vue pour qu'elle mette un message dans $_SESSION['feedback'] pour indiquer que le nouvel animal a été créé avec succès (avant la redirection).

Persistance des données de formulaire

On veut maintenant appliquer le POST-redirect-GET dans le cas où l'ajout d'un nouvel animal a échoué à cause d'erreurs dans le formulaire. Cela nécessite d'enregistrer l'animal en cours de création dans une variable de session.

  1. Lorsque l'internaute demande page de création d'un animal, qui dans votre code s'occupe de créer la nouvelle instance de AnimalBuilder pour la passer à makeAnimalCreationPage ? Ça ne devrait pas être le routeur, qui n'est pas censé manipuler des éléments du modèle. Si ce n'est déjà fait, transférer ceci dans une méthode newAnimal du contrôleur. Vérifier que tout marche toujours.
  2. Modifier la méthode saveNewAnimal du contrôleur : si l'animal créé par l'internaute est invalide, enregistrer l'instance de AnimalBuilder dans la variable de session $_SESSION['currentNewAnimal'].
  3. Modifier la méthode newAnimal pour qu'elle utilise l'instance de AnimalBuilder stockée en session si elle existe, plutôt que d'en créer une nouvelle.
  4. Tester : si on soumet un animal invalide, le formulaire devrait rester pré-rempli même si on change de page et qu'on revient.
  5. Ajouter une méthode displayAnimalCreationFailure() à la vue, qui ajoute un message de feedback en session et redirige le client vers la page de création d'un animal. Modifier le contrôleur pour qu'il appelle cette méthode au lieu d'afficher le formulaire lorsque l'animal soumis est invalide.
  6. Tester : il devrait être possible d'actualiser après soumission d'un animal invalide. Il ne reste plus qu'à supprimer la variable de session lors d'une soumission réussie.

Compléments (optionnel)

Les principes présentés dans cet exercice devront être appliqués au reste de l'architecture (modification et suppression). Il pourrait aussi être une bonne idée de regarder les compléments dans les exercices des TP précédents (mais l'exercice qui suit est prioritaire).

Exercice 4 — Authentification dans MVCR

Mise en place des comptes dans l'architecture

  1. Créer une classe Account qui représente un compte utilisateur (nom, login, mot de passe et statut). Créer une interface AccountStorage pour manipuler des comptes en BD. On ne s'occupe pas encore de création, modification et suppression ; en revanche on va avoir besoin d'une méthode checkAuth($login, $password), qui est censée renvoyer l'instance de Account correspondant au couple login-mot de passe s'il est correct, et null sinon.
  2. Créer une classe AccountStorageStub qui implémente AccountStorage avec un tableau écrit en dur.

Authentification

  1. Ajouter une méthode makeLoginFormPage à la vue. Faire le nécessaire dans le routeur pour que le site comporte une page dédiée à la connexion des internautes. Ajouter un lien vers cette page de connexion dans le menu.
  2. Implémenter la vérification de la connexion dans le contrôleur. Si les informations sont valides, le compte correspondant est récupéré en BD, et placé dans une variable $_SESSION['user']. Le contrôleur appelle ensuite une méthode de la vue qui effectue une redirection vers la page d'accueil avec un feedback.
  3. Restreindre l'accès des internautes non connecté·e·s à seulement la page d'accueil, la page de connexion et la liste des animaux, en vérifiant la valeur de $_SESSION['user'].
  4. Implémenter la déconnexion. Ajouter un lien sur la page d'accueil pour tester. (Dans la section suivante, on gérera ça plus proprement.)

Affichage public/privé

Pour l'instant, le site s'affiche de la même façon pour tout le monde (que la personne soit connectée ou non). C'est un peu absurde, en particulier pour le menu : le lien « nouvelle couleur » ne concerne que les connecté·e·s, le lien « Se connecter » ne concerne que les autres, etc. On va changer ça en séparant la vue en deux versions.

  1. Créer une classe PrivateView qui hérite de View. Son constructeur prendra une instance de Account en plus des autres paramètres. Le routeur construira une instance de PrivateView plutôt que View si l'internaute est connecté·e.
  2. S'arranger pour que le menu soit différent dans PrivateView. Typiquement, l'attribut $menu dans la vue de base devrait être rempli avec une méthode getMenu, cette méthode étant redéfinie dans PrivateView. En particulier, on va afficher le lien de déconnexion à la place du lien de connexion pour les internautes connecté·e·s.
  3. Redéfinir la page d'accueil dans la vue privée pour saluer l'internaute connecté·e.

Compléments (optionnel)

Gérer les accès plus précisément :

  • un animal ne doit pouvoir être édité ou supprimé que par la personne qui l'a créé (cela nécessite d'ajouter des informations dans la base)
  • les admins doivent pouvoir éditer et supprimer tous les animaux.

Pour faire ce genre de chose de manière sécurisée, une solution est de déclarer dans le routeur un tableau contenant la liste des actions autorisées pour l'internaute connecté·e, et de tester si l'action demandée est dans la liste avant la gestion des actions. Autrement dit, toutes les pages sont interdites par défaut : il faudra explicitement autoriser l'accès dans chaque cas.