Cours Laravel 6 – les données – l’oubli du mot de passe
Un mot de passe est plus facile à oublier qu’à retenir, d’autant qu’on en est littéralement submergé ! Toute application avec une authentification doit prévoir ce genre de situation et donner la possibilité aux utilisateurs de se sortir de ce mauvais pas. Le plus simple est de leur permettre de créer un nouveau mot de passe. Laravel est équipé pour cela et nous allons le voir dans ce chapitre.
Le présent chapitre est une suite du précédent et il faut avoir mis en place ce qui concerne l’authentification.
La base de données
Avec les migrations réalisées dans le chapitre précédent il y a la table password_resets dans notre base :
On voit qu’on va mémoriser ici l’adresse email, le jeton (token) et le timestamp (par défaut les jetons sont valables pendant une heure). On trouve ces réglages dans le fichier config/auth.php :
'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ],
Les routes et les contrôleurs
On a 4 routes pour le renouvellement du mot de passe :
Remarquez l’application du middleware guest sur toutes ces routes.
On dispose également de 2 contrôleurs :
Première étape : la demande
Pour l’utilisateur la première étape va consister à cliquer sur le lien « Forgot You Password? » prévu sur la vue de connexion :
Ce lien correspond à cette route :
On appelle la méthode showLinkRequestForm du contrôleur ForgotPasswordController. Si vous regardez dans ce contrôleur vous n’allez pas trouver cette méthode mais un trait :
use SendsPasswordResetEmails;
L’espace de nom complet est Illuminate\Foundation\Auth\SendsPasswordResetEmails. Ce trait est dans le framework et voici la méthode showLinkRequestForm :
public function showLinkRequestForm() { return view('auth.passwords.email'); }
On utilise la vue auth.passwords.email :
Avec un formulaire qui a cet aspect :
On demande l’adresse email à l’utilisateur. La soumission correspond à cette route :
On appelle la méthode sendResetLinkEmail du contrôleur ForgotPasswordController. Cette fois encore la méthode est dans le trait SendsPasswordResetEmails.
Dans ce trait il y a la validation :
$this->validate($request, ['email' => 'required|email']);
On peut vérifier que ça fonctionne :
Si la validation passe avec succès on envoie un email à l’utilisateur. Voici le message reçu :
L’envoi de l’email se fait avec un système de notification dont je vous parlerai dans la troisième partie de ce cours.
Et si tout s’est bien passé on renvoie le formulaire avec un message :
return $response == Password::RESET_LINK_SENT ? $this->sendResetLinkResponse($request, $response) : $this->sendResetLinkFailedResponse($request, $response);
Voici ce que ça donne :
Dans la table un jeton (token) a été généré :
Il sera ainsi possible de vérifier la provenance de la demande.
Deuxième étape : le renouvellement
Quand on appuie sur le bouton du message ou si on clique sur le lien de secours on utilise cette route :
On appelle la méthode showResetForm du contrôleur ResetPasswordController. Si vous regardez dans ce contrôleur vous n’allez encore pas trouver cette méthode mais un trait :
use ResetsPasswords;
L’espace de nom complet est Illuminate\Foundation\Auth\ResetsPasswords. Ce trait est dans le framework et voici la méthode showResetForm :
public function showResetForm(Request $request, $token = null) { return view('auth.passwords.reset')->with( ['token' => $token, 'email' => $request->email] ); }
On utilise la vue auth.passwords.reset en lui transmettant le jeton (token) et l’email :
Voici l’aspect du formulaire :
Dans ce formulaire on retrouve le jeton (token) dans un contrôle caché :
<input type="hidden" name="token" value="RHD4lUZLcmKfSVyvzYzpvIZIpZIKhtlmZIx6tO2V">
La soumission de ce formulaire utilise cette route :
On appelle la méthode reset du contrôleur ResetPasswordController. Cette méthode est aussi dans le trait ResetsPasswords.
On commence par une validation :
$this->validate($request, $this->rules(), $this->validationErrorMessages());
On trouve les règles (rules) dans cette méthode :
protected function rules() { return [ 'token' => 'required', 'email' => 'required|email', 'password' => 'required|confirmed|min:8', ]; }
Ensuite on vérifie que l’adresse existe bien, que le jeton est bon et on procède à la mémorisation du nouveau mot de passe :
$response = $this->broker()->reset( $this->credentials($request), function ($user, $password) { $this->resetPassword($user, $password); } );
Enfin si tout va bien on connecte l’utilisateur avec un message :
En résumé
- Un système complet de renouvellement du mot de passe est prévu. avec ses routes, ses contrôleurs et ses vues, en ajoutant le package laravel/ui.
- Le renouvellement se fait en deux étapes : une demande qui reçoit une réponse sous forme d’email sécurisé avec un jeton (token) puis une soumission du nouveau mot de passe avec un formulaire.
15 commentaires
link
Dans MAIL_USERNAME et MAIL_PASSWORD j’ai renseigné mon adresse email gmail et mon mot de passe
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=mon email
MAIL_PASSWORD=mon pass
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME= »${APP_NAME} »
link
J’ai utilisé mailtrap.io et ça marche. je pense que pour Gmail je devrais avoir un problème avec ssl je verrai ça dès que possible. Merci encore pour votre assistance
link
Bonjour à vous !
Merci bestmomo pour ce magnifique tutoriel.
J’ai un soucis au moment de la validation de l’email pour la réinitialisation du mot de passe. lors de la validation j’ai cette réponse :
Swift_TransportException
Cannot send message without a sender address
Que faire ? merci.
bestmomo
Bonjour,
Il faut renseigner MAIL_FROM_ADDRESS dans le fichier .env.
link
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=null
MAIL_PASSWORD=mon_mot_de_pass
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=mon_addresse_email
MAIL_FROM_NAME= »${APP_NAME} »
Merci pour votre réponse très rapide. voilà comment j’ai rempli mais il me renvoie toujours la même erreur.
bestmomo
La configuration ne serait pas en cache par hasard ?
link
Swift_TransportException
Connection to smtp.gmail.com:465 Timed Out
là c’est la nouvelle erreur qui m’est présentée
bestmomo
Tu as bien précisé USERNAME et PASSWORD pour gmail ?
cedrix
Bonjour,
Et bien non ça ne marche pas puisque moi également en fait le constat: Le framework paramètre mappe bien le renouvellement à l’url http://localhost/password/reset et oublie le répertoire racine ! A mon sens, les auteurs auraient comme même pu transcrire cette méthode en route lors de l’installation des fichiers auth au lien d’en faire une méthode « masquée »..
Du coup Alcar81, on ne sait pas si tu as trouvé la solution pour la réecriture de l’url puisque tu passes à un autre pb..
Je vais donc essayer de voir comment surcharger la route password.reset (certainement dans le contrôleur resetPasswordController) puis de l’indiquer ici pour les suivants.
cedrix
Re-Bonjour à tous !
Pour tout ceux qui ont un lien erroné concernant le bouton de reset du mot de passe envoyé par mail (le nom de l’application qui était erroné), la procédure peut être un peu fastidieuse sur le moment et dépasser l’objet de ce chapitre. En gros on créé une nouvelle notification (ex: sendPasswordResetNotification) dans notre application et recréer entièrement le mail dans la méthode « toMail » (sujet, expediteur, corps du texte et surtout notre fameux lien, corrigé, qui sera « /password/reset »);
D’après ce que j’ai pu lire, c’est la méthode sendPasswordResetNotification du trait CanResetPassword qui se charge de formatter le message en temps normal, mais chez moi la partie config(‘app.url’) retourne bizarrement une chaine vide (alors que définie avec le nom de mon application dans le fichier env.).
Du coup, il faut simplement surcharger cette méthode dans User.php créé précédemment dans laquelle on va instancier notre notification avec le jeton token.
Je vous donne le lien:
http://novate.co.uk/changing-the-laravel-5-3-password-reset-email-text/
C’est normalement pour du Laravel 5.3 mais visiblement très peu de changement ont été apporté sur la partie authentification (chez moi ça a marché) jusqu’à cette 6ième mouture.
beegeezzz
Pour tout ceux qui ont l’url erronnée lors de l’appui sur le bouton du mail reçu de Laravel, il suffit de modifier le fichier .env :
ça : APP_URL=http://localhost
par ça : APP_URL=http://localhost:8888/laravel6/public
alcar81
je viens de trouver un petit problème, le lien envoyé par courriel est:
http://localhost/password/reset/db121bed797648879833d0ead6cc3f48ec53d9d2dc5603ab38c979a0b34efb27?email=alexandre.carignan%40alxmultimedia.com
Mais le lien devrait être:
http://localhost/laravel6/public/password/reset/db121bed797648879833d0ead6cc3f48ec53d9d2dc5603ab38c979a0b34efb27?email=alexandre.carignan%40alxmultimedia.com
Pour réussir à le tester.
Bonne journée.
alcar81
Après ce chapitre, l’envoie de courriel ne semble pas marché, je ne reçois pas le courriel. Mon serveur smtp est fonctionnel et paramétré dans .env.
Est-ce que je devrais paramétrer autre chose? merci.
alcar81
problème résolu, il ne faut pas oublier de modifier ceci: BROADCAST_DRIVER=smtp, il était à BROADCAST_DRIVER=log.
Bonne journée.
bestmomo
Salut,
Ça devrait fonctionner sans toucher à ce paramètre…