Créer une page de login

Transcription

Créer une page de login
Astuce
Image not readable or empty
/extension/devnotebook/design/devnotebook/images/icon/trick.png
Créer une page de login
Objectif
Le but de cet article est de proposer un exemple de page de connexion. Il s'articule autour de deux fichiers
principaux : un template Twig et un contrôleur PHP. Il est réalisé entièrement en mode Symfony, sans
utiliser le stack Legacy.
Si l'utilisateur saisit de mauvais identifiants, un message d'erreur est affiché. Une fois connecté, il est redirigé
vers la page qu'il consultait avant de se connecter.
Pré-requis
Vous avez déjà créé le Bundle Acme/MyBundle, et l'avez déclaré dans le fichier
ezpublish/EzPublishKernel.php.
Le pagelayout utilisé par défaut est AcmeMyBundle::pagelayout.html.twig. Il possède un bloc nommé
col_main.
Dans le pagelayout, la variable redirect_uri doit être définie et contenir l'url courante ex: ('/Marubrique/Mon-article').
Création du template
Dans le répertoire de templates de votre bundle (Resources/views), créez les répertoires modules/user/, qui
contiendront tous les templates concernant la gestion des utilisateurs (connexion, inscription, ...)
Créez maintenant le fichier login.html.twig dans le répertoire user.
Voici à quoi il peut ressembler :
{# Surcharge du bloc 'col_main' du template pagelayout.html.twig, pour la page de connexion #}
{% extends noLayout ? viewbaseLayout : "AcmeMyBundle::pagelayout.html.twig" %}
{#
Affiche un article en mode Full
Paramètres :
- noLayout
- fail_login
- redirect_uri
#}
: False
: Si la connexion a échouée
: URI vers laquelle rediriger après la connexion
{% block col_main %}
<div class="main-content user user-login panel">
{# Titre #}
<header class="heading">
<h1>Connexion</h1>
</header>
{# Contenu #}
<div class="content-body">
{# Message d'erreur #}
{% if fail_login %}
<div class="alert alert-danger">
<button data-dismiss="alert" class="close" type="button">×</button>
<p><strong>Erreur !</strong></p>
<p>Identifiant ou mot de passe invalide.</p>
</div>
{% endif %}
{# Formulaire #}
<form class="form-horizontal" action=
"{{ path( 'acme_my_user_login', { 'redirectURI': redirect_uri } ) }}" method="post">
<div class="form-group {% if fail_login %}has-error{% endif %}">
<label class="col-lg-3 control-label" for="login">Identifiant</label>
<div class="col-lg-4">
<input type="text" placeholder="Identifiant" id="login" name=
"Login" class="form-control input-small">
</div>
<div class="validation col-lg-5">
<img src="{{ asset( "bundles/acmemy/images/error.png" ) }}" alt=
"Erreur" />
</div>
</div>
<div class="form-group {% if fail_login %}has-error{% endif %}">
<label class="col-lg-3 control-label" for="password">Mot de passe</
label>
<div class="col-lg-4">
<input type="password" placeholder="Mot de passe" id="password"
name="Password" class="form-control input-small">
</div>
<div class="validation col-lg-5">
<img src="{{ asset( "bundles/acmemy/images/error.png" ) }}" alt=
"Erreur" />
</div>
</div>
<div class="form-group">
<div class="col-lg-10 text-right">
<button class="btn btn-primary" type="submit">Connexion</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
Explications :
Ligne 2, on commence par étendre le pagelayout par défaut pour modifier le bloc principal.
Juste en dessous, on liste les paramètres nécessaires au template pour afficher la page correctement.
Ensuite, on commence la surcharge du bloc principal de la page : col_main.
On affiche un message d'erreur si les identifiants sont mauvais ({% if fail_login %}).
On affiche un formulaire avec un champ identifiant et un champ mot de passe.
Le formulaire pointe vers la route acme_my_user_login, sur laquelle Symfony va brancher le futur
contrôleur. L'URL courante lui sera transmise en argument.
Remarques :
L'image d'erreur doit être présente dans le répertoire Resources/public/images du bundle.
Le template utilise le framework CSS Bootstrap dans sa version 3, et l'HTML 5.
Les textes devraient être entre les tags {% trans %} et {% endtrans %}, pour pouvoir être traduits
facilement par la suite si besoin.
Création du contrôleur
C'est le contrôleur qui va gérer les actions de connexion et déconnexion des utilisateurs. Il aura donc deux
actions : login et logout.
Créez le fichier ModuleUserController.php dans le répertoire Controller de votre Bundle :
namespace Acme\MyBundle\Controller;
use \eZ\Bundle\EzPublishCoreBundle\Controller;
use \eZ\Publish\API\Repository\Exceptions\NotFoundException;
use \eZ\Publish\API\Repository\Values\User\User;
use \Symfony\Component\HttpFoundation\Cookie;
use \Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Controleur pour gérer les vues du module user. */
class ModuleUserController extends Controller {
/**
* Gestion de l'affichage de la page de login.
* - Affiche la page de login par défaut
* - Affiche d'éventuelles erreur de connexion
* - Connecte et redirige l'utilisateur
*
* @param string URI vers laquelle rediriger après la déconnexion
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function loginAction( $redirectURI ) {
$failLogin = false;
// Suppression d'un éventuel doublon dans l'URI
if ( ( $offset = strpos( $redirectURI, '/user/login' ) ) === 0 ) {
$redirectURI = substr( $redirectURI, $offset );
}
$request = $this->getRequest()->request;
// Si le formulaire de connexion a été soumis
if ( $request->has( 'Login' ) && $request->has( 'Password' ) ) {
$login
= $request->get( 'Login' );
$password
= $request->get( 'Password' );
if ( trim( $login ) != '' && trim( $password ) != '' ) {
$userService = $this->getRepository()->getUserService();
try {
$user = $userService->loadUserByCredentials( $login, $password );
return $this->connectUser( $user, $redirectURI );
} catch (NotFoundException $e) {
$failLogin = true;
}
} else {
$failLogin = true;
}
}
return $this->render(
'AcmeMyBundle:modules\user:login.html.twig',
array(
'noLayout'
=> false,
'fail_login'
=> $failLogin,
'redirect_uri' => $redirectURI
)
);
}
/**
* Déconnecte l'utilisateur courant.
*
* @param string URI vers laquelle rediriger après la déconnexion
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException Si l'utilisateur anonyme
*/
public function logoutAction( $redirectURI ) {
// Suppression d'un éventuel doublon dans l'URI
if ( ( $offset = strpos( $redirectURI, '/user/logout' ) ) === 0 ) {
$redirectURI = substr( $redirectURI, $offset );
}
// Récupération de l'utilisateur anonyme
$userService = $this->getRepository()->getUserService();
$anonymousUser = $userService->loadAnonymousUser();
return $this->connectUser( $anonymousUser, $redirectURI );
}
/**
* Connecte l'utilisateur en argument et retourne une redirection 302.
* Si l'utilisateur en argument est anonyme, alors c'est une déconnexion.
*
* @param \eZ\Publish\API\Repository\Values\User\User $user L'utilisateur à connecter
* @param string $redirectURI URI vers laquelle rediriger l'utilisateur après connexion
*
* @return RedirectResponse
*/
protected function connectUser( User $user, $redirectURI = '/' ) {
$repository = $this->getRepository();
$repository->setCurrentUser( $user );
$session
= $this->getRequest()->getSession();
try {
$response = new RedirectResponse( $redirectURI );
} catch (NotFoundException $e) {
$response = new RedirectResponse( '/' );
}
$userService
= $repository->getUserService();
$anonymousUser = $userService->loadAnonymousUser();
// Si l'utilisateur en argument est anonyme
if ( $user->id === $anonymousUser->id ) {
// Déconnexion de l'utilisateur courant
$response->headers->setCookie( new Cookie( 'is_logged_in', 'false' ) );
$session->remove( 'eZUserLoggedInID' );
} else {
// Connexion de l'utilisateur
$response->headers->setCookie( new Cookie( 'is_logged_in', 'true' ) );
$session->set( 'eZUserLoggedInID', $user->id );
}
return $response;
}
}
Explications :
Le contrôleur est une classe PHP qui étend la classe Controller du Bundle
eZ\Bundle\EzPublishCoreBundle fourni par eZ Publish.
Ses deux premières méthodes sont des actions et leurs noms finissent d'ailleurs par Action. Elles
retournent un objet Response.
La troisième est une méthode utilitaire pour connecter un utilisateur.
Par défaut, loginAction() inclus le template de login dans sa réponse, grâce aux lignes :
return $this->render(
'AcmeMyBundle:modules\user:login.html.twig',
array(
'noLayout'
=> false,
'fail_login'
=> $failLogin,
'redirect_uri' => $redirectURI
)
);
Si le formulaire est soumis et valide, on appelle la méthode connectUser() qui connecte l'utilisateur et
fournit une réponse de type redirection.
Configuration de la route
Pour que Symfony sache quoi faire lorsqu'on appelle la page http://mon-site/user/login, il faut modifier le fichier
Resources/config.routing.yml dans votre bundle.
Ajoutez-y les deux routes suivantes, pour se connecter et se déconnecter :
acme_my_user_login:
pattern: /user/login{redirectURI}
defaults: { _controller: AcmeMyBundle:ModuleUser:login }
requirements:
redirectURI: ".*"
acme_my_user_logout:
pattern: /user/logout{redirectURI}
defaults: { _controller: AcmeMyBundle:ModuleUser:logout }
requirements:
redirectURI: ".*"
Explications :
Une route doit être nommée par un identifiant unique de votre choix (ex : acme_my_user_login). C'est lui
qui est appelé dans la fonction path() côté template.
Elle associe un pattern à une action d'un contrôleur.
Pour la première route, si on appelle la page /user/login<quelque chose>, la méthode loginAction()
du contrôleur ModuleUserController du bundle AcmeMyBundle sera exécutée. La méthode recevra
"quelque chose" en argument.
Les éléments dans requirements permettent entre autres de spécifier la forme que doit avoir le
paramètre. Ici, n'importe qu'elle chaîne est autorisée.
Publié le : 09/12/2013 Modifié le : 10/04/2015