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.
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 13 :
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) :
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 . Remarquez aussi que j'ai précisé que le nom doit être unique, cela va créer automatiquement un index pour celle 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 :
On vérifie que la table est bien créée :
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 :
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 !
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 crypté pour de raisons de sécurité. Laravel nous propose la classe Hash pour effectuer ce cryptage. Voilà le code pour ajouter deux utilisateurs :
DB::table('users')->insert( array( array('username' => 'LeGros', 'password' => Hash::make('passeLeGros')), array('username' => 'LeMaigre', 'password' => Hash::make('passeLeMaigre')) ) );Vérifions dans la base :
Le résultat est satisfaisant et les mots de passe sont correctement cryptés.
Un formulaire de connexion
Créons à présent un formulaire de connexion app/views/connexion.php :<!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 :
Route::get('/', function() { return View::make('connexion'); });
Avec l'URL http://localhost/laravel/public on obtient le formulaire :
Traitement de la réponse au formulaire
Entrez ce code dans les routes :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. A la place du nom ça pourrait être autre chose comme un mail, 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 .
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 :
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 :
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é. C'est quoi 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 :
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 .
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 :
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" :
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 :
On voit apparaître un troisième cookie nommé remember qui expire en 2018 .
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 notre :
<input type="hidden" value="7TorWnP8iZUxyeet6z8MfKAZnt8Mz6qKZaSh64pU" name="_token">
Et la route pour le traitement du retour du formulaire :
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 :
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.
Par bestmomo
Nombre de commentaires : 9