Développer une application avec le framework Play !


précédentsommairesuivant

IX. Ajout de l'authentification

Attaquons-nous désormais à un aspect important de notre site : l'authentification. Heureusement, Play propose un module pour cela ! Il s'agit du module Secure.

IX-A. Activation du module Secure

A l'image du module CRUD, il faut activer le module Secure en modifiant notre fichier /yabe/conf/application.properties, puis redémarrer le serveur :

 
Sélectionnez
# Import the secure module
module.secure=${play.path}/modules/secure

Normalement, lors du redémarrage, nous devrions être informé que ce module a été chargé.

Comme précédemment, ce module vient avec une série de routes prédéfinies que nous pouvons activer en éditant le fichier /yabe/conf/routes (nous pourrions bien sûr créer nos propres routes, si cela était nécessaire) :

 
Sélectionnez
# Import Secure routes
*       /                                       module:secure

IX-B. Protection de l'interface d'administration

En réalité, ce module propose un contrôleur controllers.Secure qui déclare tous les intercepteurs requis. Nous pourrions étendre cette classe Java, mais nous serions alors confrontés à la limitation du simple héritage de Java.

Ainsi, au lieu d'hériter directement de ce contrôleur, nous pouvons annoter notre contrôleur d'administration avec @With, qui indiquera à Play d'invoquer également les intercepteurs adéquats :

 
Sélectionnez
package controllers;
 
import play.*;
import play.mvc.*;
 
@With(Secure.class)
public class Posts extends CRUD {    
}

Nous modifions de la même façon les classes Comment, User et Tag.

Si nous souhaitons accéder à la page d'administration, nous arrivons en réalité sur une page de connexion :

Image non disponible

Pour l'heure, il suffit de renseigner n'importe quel couple login et mot de passe pour pouvoir passer cet écran.

IX-C. Configuration du processus d'authentification

Notre application doit disposer d'une instance du contrôleur controllers.Secure.Security afin de nous permettre de configurer le processus d'authentification. C'est grâce à cette implémentation que nous pourrons spécifier la manière exacte dont les utilisateurs devront s'authentifier.

Créons un fichier /yabe/controllers/Security.java et surchargeons la méthode authentify() :

 
Sélectionnez
package controllers;
 
import models.*;
 
public class Security extends Secure.Security {
 
    static boolean authentify(String username, String password) {
        return true;
    }
    
}

Etant donné que nous disposons déjà d'un objet User, il est simple de créer une version fonctionnelle de cette méthode :

 
Sélectionnez
static boolean authentify(String username, String password) {
    return User.connect(username, password) != null;
}

Maintenant, rendons-nous à l'adresse http://localhost:9000/logout pour se déconnecter, et réessayons de se connecter en utilisant cette fois-ci un utilisateur existant dans le fichier data.yml, tel que bob@gmail.com / secret.

IX-D. Refactorisation de l'interface d'administration

Nous avions construit notre interface d'administration en nous appuyant sur le module CRUD. Toutefois, cela s'intègre assez mal avec l'aspect visuel du reste du site. Nous allons donc travailler sur une nouvelle interface d'administration. Cette nouvelle mouture permettra à chaque auteur d'avoir accès à ses propres billets. Toutefois, nous conserverons l'administration basée sur le module CRUD pour les "super administrateurs".

Créons un nouveau contrôleur qui gèrera la partie administration :

 
Sélectionnez
package controllers;
 
import play.*;
import play.mvc.*;
 
import java.util.*;
 
import models.*;
 
@With(Secure.class)
public class Admin extends Controller {
    
    @Before
    static void setConnectedUser() {
        if(Security.isConnected()) {
            User user = User.find("byEmail", Security.connected()).first();
            renderArgs.put("user", user.fullname);
        }
    }
 
    public static void index() {
        render();
    }
    
}

Refactorisons les routes du fichier /yabe/conf/routes :

 
Sélectionnez
# Administration
GET     /admin/?                                Admin.index
*       /admin                                  module:crud

Maintenant, lions le texte "Se connecter pour écrire quelque chose" (Log in to write something) situé dans le fichier /yabe/app/views/main.html à ce contrôleur :

 
Sélectionnez
...
<ul id="tools">
    <li>
        <a href="@{Admin.index()}">Log in to write something</a>
    </li>
</ul>
...

La dernière étape est de créer le template /yabe/app/views/Admin/index.html, en commençant par quelque chose de simple :

 
Sélectionnez
Welcome ${user}!

Revenons sur la page d'accueil de notre blog, et cliquons sur ce fameux lien. Si tout s'est bien passé, nous devrions être redirigés vers la nouvelle page d'administration :

Image non disponible

C'est un bon début. Comme nous souhaitons disposer de plusieurs pages dans l'interface d'administration, nous allons créer un super template. Choisissons le fichier /yabe/app/views/admin.html pour l'y accueillir :

 
Sélectionnez
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Administration</title>		
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        #{get 'moreStyles' /}	
        <link rel="stylesheet" type="text/css" media="screen" 
                href="@{'/public/stylesheets/main.css'}" />
        <link rel="shortcut icon" type="image/png" 
                href="@{'/public/images/favicon.png'}" />
        <script src="@{'/public/javascripts/jquery-1.3.2.min.js'}"></script>
        <script src="@{'/public/javascripts/jquery.tools.min.js'}"></script>
    </head>
    <body id="admin">
        
        <div id="header">
            <div id="logo">
                yabe. <span>administration</span>
            </div>
            <ul id="tools">
                <li>
                    <a href="@{Secure.logout()}">Log out</a>
                </li>
            </ul>
        </div>
        
        <div id="main">
            #{doLayout /} 
        </div>
        
        <p id="footer">
            Yabe is a (not so) powerful blog engine built with the 
            <a href="http://www.playframework.org">play framework</a>
            as a tutorial application.
        </p>
        
    </body>
</html>

Vous pourrez constater que cela est assez proche de ce que nous avons déjà fait pour la page de garde de notre blog. Nous avons changé le lien de connexion par un lien de déconnexion, qui appelle l'action du contrôleur Secure offert par le module de sécurité.

Faisons désormais usage de ce nouveau template dans le fichier /yabe/app/views/Admin/index.html :

 
Sélectionnez
#{extends 'admin.html' /}
 
Welcome ${user}!

Rafraichissons la page :

Image non disponible

Si nous nous déconnectons, nous sommes redirigés vers l'écran de connexion :

Image non disponible

C'est là la manière classique utilisée par le module de sécurité pour gérer les événements de déconnexion. Cela reste configurable très simplement en surchargeant la méthode onDisconnected() :

 
Sélectionnez
static void onDisconnected() {
    Application.index();
}

Nous pouvons procéder de même avec l'événement onAuthenticated() :

 
Sélectionnez
static void onAuthenticated() {
    Admin.index();
}

IX-E. Ajout des rôles

Concrètement, nous avons besoin de deux types d'interface d'administration : la première permettant l'écriture de billet, la seconde pour les super administrateurs. Nous avions ajouté dans la classe User une méthode isAdmin() qui indique justement si cet utilisateur dispose des droits d'administration.

Le module de sécurité offre non seulement le mécanisme d'authentification, mais également la gestion des autorisations. Cela s'appelle les profils. Pour créer un profile administrateur, nous avons juste à surcharger la méthode check() dans la classe controllers.Security :

 
Sélectionnez
static boolean check(String profile) {
    if("admin".equals(profile)) {
        return User.find("byEmail", connected()).<User>first().isAdmin;
    }
    return false;
}

Nous pouvons dès à présent créer un menu dans l'interface d'administration qui dépendra du profil. Modifions le fichier /yabe/view/main.html pour y ajouter un menu en haut :

 
Sélectionnez
...
<div id="main">
    
    <ul id="adminMenu">
        <li class="${request.controller == 'Admin' ? 'selected' : ''}">
            <a href="@{Admin.index()}">My posts</a>
        </li>
        #{secure.check 'admin'}
            <li class="${request.controller == 'Posts' ? 'selected' : ''}">
                <a href="@{Posts.list()}">Posts</a>
            </li>
            <li class="${request.controller == 'Tags' ? 'selected' : ''}">
                <a href="@{Tags.list()}">Tags</a>
            </li>
            <li class="${request.controller == 'Comments' ? 'selected' : ''}">
                <a href="@{Comments.list()}">Comments</a>
            </li>
            <li class="${request.controller == 'Users' ? 'selected' : ''}">
                <a href="@{Users.list()}">Users</a>
            </li>
        #{/secure.check}
    </ul>
    
    #{doLayout /} 
</div>
...

Remarquez comment nous avons utilisé la balise #{secure.check /} pour afficher les options spécifiques aux administrateurs.

Image non disponible

Cela n'est toutefois pas suffisant pour protéger la partie CRUD. Si un utilisateur connaît la bonne URL, il pourra y accéder ! Nous devons ainsi protéger les contrôleurs de la même façon. Cela se fait très simplement, grâce à l'annotation @Check. Ainsi, pour le contrôleur Post :

 
Sélectionnez
package controllers;
 
import play.*;
import play.mvc.*;
 
@Check("admin")
@With(Secure.class)
public class Posts extends CRUD {    
}

Procédons de même pour les contrôleurs Tags, Comments et Users. Déconnectons-nous, puis essayons de nous connecter avec un utilisateur simple, par exemple jeff@gmail.com / secret. Normalement, nous ne devons pas voir le menu des administrateurs. De plus, une tentative d'accès direct à l'adresse http://localhost:9000/admin/users devrait nous retourner une erreur 403 (accès refusé) :

Image non disponible

IX-F. Configurer la mise en page du CRUD

Lorsque nous accédons à la partie CRUD de l'interface d'administration, nous perdons la mise en page de cette dernière. Cela est dû au fait que le module CRUD propose sa propre mise en page. Bien sûr, nous pouvons la surcharger. Commençons par lancer cette commande :

 
Sélectionnez
> play crud:ov --layout

Cela nous crée un fichier /yabe/app/views/CRUD/layout.html. Remplaçons son contenu pour améliorer son intégration au reste de l'application :

 
Sélectionnez
#{extends 'admin.html' /}
#{set 'moreStyles'}
    <link rel="stylesheet" type="text/css" media="screen" 
        href="@{'/public/stylesheets/crud.css'}" />
#{/set}
 
<div id="crud">
 
    #{if flash.success}
    	<div class="crudFlash flashSuccess">
    		${flash.success}
    	</div>
    #{/if}
    #{if flash.error || error}
    	<div class="crudFlash flashError">
    		${error ?: flash.error}
    	</div>
    #{/if}
 
    <div id="crudContent">
    	#{doLayout /}
    </div>
 
</div>

Nous réutilisons le fichier crud.css et l'incluons dans le admin.html en utilisant les mécanismes de get et set des templates. Maintenant, si nous retournons sur les pages du CRUD, nous devrions constater une amélioration de leur intégration :

Image non disponible
Image non disponible

IX-G. Style de l'écran de connexion

Maintenant que notre interface d'administration est cohérente avec le reste de l'application, intéressons-nous à l'écran de connexion. Comme toujours, cet écran est configurable. Lançons la commande suivante :

 
Sélectionnez
> play secure:ov --css

Nous allons juste conserver le fichier CSS dans son état, mais avant cela, nous importons notre propre CSS (main.css). Ajoutons donc la ligne suivante dans /yabe/public/stylesheets/secure.css :

 
Sélectionnez
@import url(main.css);
...

Paramétrons finalement les messages de cet écran en ajoutant au fichier /yabe/conf/messages les lignes suivantes :

 
Sélectionnez
secure.username=Your email:
secure.password=Your password:
secure.signin=Log in now
Image non disponible

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.