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 :
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) :
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 . 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 :
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 :
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 :
Vérifions dans la base :
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 :
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 :
Avec l'URL http://localhost/laravel/public on obtient le formulaire :
XVI-A-3. Traitement de la réponse au formulaire▲
Entrez ce code dans les routes :
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 .
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 :
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 :
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 :
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 .
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 :
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 » :
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 .
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 :
<input type
=
"hidden"
value
=
"7TorWnP8iZUxyeet6z8MfKAZnt8Mz6qKZaSh64pU"
name
=
"_token"
>
Et la route pour le traitement du retour du formulaire est :
Le jeton (token) est vérifié au niveau du filtre CSRF :
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.