IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel pour apprendre à utiliser le framework Laravel 4


précédentsommairesuivant

XVI. Chapitre 16 : Authentification

Il est fréquent d'avoir besoin de filtrer les utilisateurs d'un site selon les pages affichées, les fonctions disponibles… On parle alors d'authentification. Laravel nous offre aussi une infrastructure efficace et facile à mettre en œuvre pour cette partie importante et délicate d'un site.

XVI-A. La table des utilisateurs

La première chose à faire est de créer une table dans notre base de données pour mémoriser les informations des utilisateurs. En général on se contente d'un pseudonyme, une adresse mail et un mot de passe. Par défaut la table doit se nommer users. On peut utiliser un autre nom, mais ça nous obligerait à effectuer quelques modifications, alors autant prendre la valeur par défaut. Commençons par faire une migration pour cette table comme nous l'avons vu lors du chapitre 133Chapitre 12 : Les formulaires :

Image non disponible

Et renseignons notre code pour créer la table et aussi prévoir la marche arrière au cas où (je rappelle que le fichier a été créé dans le dossier database/migrations) :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateUsers extends Migration {
 
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
      Schema::create('users', function($table) {
          $table->increments('id');
          $table->string('username', 128)->unique();
          $table->string('password', 64);
          $table->string('remember_token', 100)->nullable();
      });
  }
 
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
      Schema::drop('users');
  }
 
}

Vous pouvez changer le nom pour la ligne du pseudo, mais ne changez pas celui du mot de passe qui doit être password, ou alors relevez les manches et allez modifier quelques lignes de code Image non disponible. Remarquez aussi que j'ai précisé que le nom doit être unique, cela va créer automatiquement un index pour cette ligne. Le champ remember_token a été introduit avec la version 4.1.26 de Laravel pour des raisons de sécurité. Il ne reste plus qu'à effectuer la migration :

Image non disponible

On vérifie que la table est bien créée :

Image non disponible

C'est vraiment la prestation minimale mais ça suffira pour notre exemple. Si vous regardez maintenant dans le dossier app/models vous trouvez un modèle déjà existant nommé User. Si vous l'ouvrez, vous trouvez ce code :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
 
class User extends Eloquent implements UserInterface, RemindableInterface {
 
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';
 
    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = array('password');
 
    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        return $this->getKey();
    }
 
    /**
     * Get the password for the user.
     *
     * @return string
     */
    public function getAuthPassword()
    {
        return $this->password;
    }
 
    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     */
    public function getRememberToken()
    {
        return $this->remember_token;
    }
 
    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value)
    {
        $this->remember_token = $value;
    }
 
    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName()
    {
        return 'remember_token';
    }
 
    /**
     * Get the e-mail address where password reminders are sent.
     *
     * @return string
     */
    public function getReminderEmail()
    {
        return $this->email;
    }
 
}

Laravel est vraiment gentil avec nous !

XVI-A-1. Insertion d'utilisateurs

On va maintenant créer quelques utilisateurs mais il nous faut un peu parler du mot de passe. Celui-ci doit être chiffré pour des raisons de sécurité. Laravel nous propose la classe Hash pour effectuer ce chiffrement. Voilà le code pour ajouter deux utilisateurs :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
DB::table('users')->insert(
    array(
        array('username' => 'LeGros', 'password' => Hash::make('passeLeGros')),
        array('username' => 'LeMaigre', 'password' => Hash::make('passeLeMaigre'))
    )
);

Vérifions dans la base :

Image non disponible

Le résultat est satisfaisant et les mots de passe sont correctement chiffrés.

XVI-A-2. Un formulaire de connexion

Créons à présent un formulaire de connexion app/views/connexion.php :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h2>Connexion au site : </h2>
<?php
    echo Form::open(array('url' => 'connexion'));
    echo '<strong>',Form::label('nom', 'Nom :'),'</strong>';
    echo Form::text('nom');
    echo '<strong>',Form::label('password', 'Mot de passe :'),'</strong>';
    echo Form::password('password');
    echo Form::submit('Se connecter');
    echo Form::close();
?>
</body>
</html>

Et une route :

 
Sélectionnez
1.
2.
3.
4.
Route::get('/', function()
{
    return View::make('connexion');
});

Avec l'URL http://localhost/laravel/public on obtient le formulaire :

Image non disponible

XVI-A-3. Traitement de la réponse au formulaire

Entrez ce code dans les routes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Route::post('connexion', function()
{
    $nom = Input::get('nom');
    $passe = Input::get('password');
 
    if(Auth::attempt(array('username' => $nom, 'password' => $passe)))
        echo 'Vous êtes maintenant connecté '.Auth::user()->username;
    else
        echo 'Echec de la connexion';
});

On utilise la méthode attempt en passant comme paramètres le mot de passe et le nom. À la place du nom ça pourrait être autre chose comme un email, l'essentiel étant que cette information soit unique pour identifier l'utilisateur, ce qu'on a prévu dans la table pour les noms. Vous pouvez ajouter d'autres lignes, par exemple pour tester que l'utilisateur est actif, qu'il n'a pas été banni… Dans notre cas si le nom et le mot de passe correspondent, alors l'utilisateur est connecté, sinon il ne l'est pas. Laravel prend tout en charge, vous n'avez rien de plus à faire Image non disponible.

XVI-A-4. Filtrage des utilisateurs

L'intérêt d'une authentification est évidemment de filtrer les utilisateurs pour ne leur donner accès qu'à des ressources autorisées en fonction de leur statut. Voici une route qui applique un filtrage :

 
Sélectionnez
1.
2.
3.
4.
Route::get('zone_reservee', array('before' => 'auth', function()
{
    echo 'Vous avez bien été identifié '.Auth::user()->username;
}));

La syntaxe est limpide ! Mais où se trouve ce filtre ? Nous avons vu que tous les filtres se trouvent dans le fichier app/filters, c'est donc ici que nous trouvons les filtres de l'authentification :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
Route::filter('auth', function()
{
    if (Auth::guest()) return Redirect::route('login');
});
 
Route::filter('guest', function()
{
    if (Auth::check()) return Redirect::to('/');
});

On en trouve deux : le premier qu'on a utilisé ci-dessus auth qui vérifie si l'utilisateur est bien authentifié. Qu'est-ce que cet Auth::guest() qu'on trouve à l'intérieur ? Juste une méthode qui renvoie true si l'utilisateur n'est pas authentifié, et vous voyez que dans ce cas on le renvoie à la route login pour qu'il le fasse.

Le second filtre guest fait exactement l'inverse. Il teste que l'utilisateur est authentifié avec Auth::check(), et dans ce cas on le renvoie sur le site auquel il a accès.

Maintenant que nous avons analysé ces filtres, nous pouvons écrire des routes qui les utilisent, histoire d'avoir quelque chose de fonctionnel :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Route::get('/', array('before' => 'auth', function()
{
    echo 'Maintenant vous êtes sur le site '.Auth::user()->username;
}));
 
Route::get('login', array('as' => 'login', 'before' => 'guest', function()
{
    return View::make('connexion');
}));
 
Route::post('connexion', function()
{
    $nom = Input::get('nom');
    $passe = Input::get('password');
 
    if(Auth::attempt(array('username' => $nom, 'password' => $passe)))
        return Redirect::to('/');
    else
        return Redirect::route('login');
});

Je vous laisse analyser ce code, conjointement avec celui des deux filtres pour comprendre comment tout ça se boucle. Remarquez que j'ai nommé la route login parce que le filtre attend ce nom de route ; j'aurais aussi pu changer la syntaxe du filtre mais comme ça vous voyez à nouveau un nommage de route Image non disponible.

XVI-A-5. Se rappeler de moi

On prévoit souvent sur les sites une option « Se rappeler de moi », pour éviter d'avoir à s'authentifier à nouveau la prochaine fois qu'on visite le site. Ici aussi Laravel nous simplifie la vie. Mais voyons déjà les cookies utilisés pour une authentification simple :

Image non disponible

On trouve deux cookies, le premier valide pour la durée de la session et le second valide pendant deux heures. Modifions le code pour avoir l'option « Se rappeler de moi » :

 
Sélectionnez
if(Auth::attempt(array('username' => $nom, 'password' => $passe), true))

J'ai juste ajouté un paramètre à la méthode attempt avec la valeur true. Regardons maintenant les cookies quand je me connecte :

Image non disponible

On voit apparaître un troisième cookie nommé remember qui expire en 2018 Image non disponible.

XVI-A-6. Protection CSRF

Il est toujours prudent de se protéger contre le cross-site et Laravel implante systématiquement cette protection pour les formulaires. Regardez le contrôle caché qui a été généré dans le nôtre :

 
Sélectionnez
<input type="hidden" value="7TorWnP8iZUxyeet6z8MfKAZnt8Mz6qKZaSh64pU" name="_token">

Et la route pour le traitement du retour du formulaire est :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Route::post('connexion', array('before' => 'csrf', function()
{
    $nom = Input::get('nom');
    $passe = Input::get('password');
 
    if(Auth::attempt(array('username' => $nom, 'password' => $passe)))
        return Redirect::to('/');
    else
        return Redirect::route('login');
}));

Le jeton (token) est vérifié au niveau du filtre CSRF :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
Route::filter('csrf', function()
{
    if (Session::token() != Input::get('_token'))
    {
        throw new Illuminate\Session\TokenMismatchException;
    }
});

On vérifie que le jeton envoyé correspond à celui qui a été placé en session.

On a fait le tour de l'essentiel de l'authentification, vous trouverez des informations complémentaires, comme d'habitude, dans la documentation.


précédentsommairesuivant

Copyright © 2017 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.