web-dev-qa-db-fra.com

Comment créer une méthode de réinitialisation de mot de passe dans Laravel lors de l'utilisation du fournisseur d'utilisateurs de base de données

J'ai cherché sur Internet et je n'ai pas encore trouvé de solution au problème suivant ...

Nous avons actuellement un site Web développé en utilisant Laravel dont la table utilisateur est une base de données Microsoft SQL distante. Le pilote dans config/auth.php a été défini sur "base de données". Tout fonctionne bien, à l'exception de la fonctionnalité de réinitialisation du mot de passe, qui nous donne l'erreur suivante:

UnexpectedValueException in PasswordBroker.php line 238: User must implement CanResetPassword interface.

D'après ma compréhension limitée de Laravel (c'est ma première expérience avec Laravel), le pilote Eloquent prend en charge la fonctionnalité CanResetPassword, cependant, cela n'a pas été implémenté dans le fournisseur d'utilisateur de base de données par Laravel, d'où l'erreur.

Ma question est donc la suivante: quelqu'un a-t-il eu une configuration où il a le pilote de "base de données" et a mis en œuvre une fonctionnalité de réinitialisation du mot de passe? Tous les exemples que j'ai vus à ce jour concernent l'utilisation du modèle Eloquent, qui d'après ma compréhension de Laravel n'est pas une option car pendant le développement initial, nous avons dû changer le pilote d'Eloquent en base de données en obtenir le serveur Microsoft SQL distant fonctionne en premier lieu. Déplacer la base de données Microsoft SQL vers une base de données locale n'est pas une option, je le crains.

Alternativement, si quelqu'un a implémenté une autre méthode pour réinitialiser son mot de passe à l'aide d'une adresse e-mail, je serais ouvert aux suggestions.

10
short_coder

Pour écrire votre propre logique de réinitialisation de mot de passe, vous pouvez toujours utiliser la migration par défaut qui sort de la boîte ou simplement créer la vôtre. La partie la plus importante est le jeton. Parce que vous effectuez votre propre réinitialisation de mot de passe, vous avez quelques décisions à prendre:

  • Le jeton expirera-t-il?
  • Un utilisateur peut-il utiliser le même jeton plusieurs fois?

Vous aurez besoin de 2 pages, 4 itinéraires différents et 4 fonctions différentes dans le même contrôleur. La page "J'ai oublié mon mot de passe" et la page "Réinitialiser le mot de passe". Dans la première page, affichez un formulaire dans lequel vous prenez l'email de l'utilisateur. Et postez sur le contrôleur suivant.

//to be added on top as use statements 
use DB;
use Auth;
use Hash;
use Carbon;
use App\User;

public function sendPasswordResetToken(Request $request)
{
    $user = User::where ('email', $request->email)-first();
    if ( !$user ) return redirect()->back()->withErrors(['error' => '404']);

    //create a new token to be sent to the user. 
    DB::table('password_resets')->insert([
        'email' => $request->email,
        'token' => str_random(60), //change 60 to any length you want
        'created_at' => Carbon::now()
    ]);

    $tokenData = DB::table('password_resets')
    ->where('email', $request->email)->first();

   $token = $tokenData->token;
   $email = $request->email; // or $email = $tokenData->email;

   /**
    * Send email to the email above with a link to your password reset
    * something like url('password-reset/' . $token)
    * Sending email varies according to your Laravel version. Very easy to implement
    */
}

Deuxième partie, lorsque l'utilisateur clique sur le lien

/**
 * Assuming the URL looks like this 
 * http://localhost/password-reset/random-string-here
 * You check if the user and the token exist and display a page
 */

 public function showPasswordResetForm($token)
 {
     $tokenData = DB::table('password_resets')
     ->where('token', $token)->first();

     if ( !$tokenData ) return redirect()->to('home'); //redirect them anywhere you want if the token does not exist.
     return view('passwords.show');
 }

Afficher une page avec un formulaire contenant 2 entrées - Nouveau mot de passe password ou ce que vous voulez - Confirmation du nouveau mot de passe password_confirm ou ce que vous voulez Le formulaire doit être publié sur la même URL mappée vers le contrôleur suivant. Pourquoi? car nous devons encore utiliser le jeton pour trouver l'utilisateur réel.

 public function resetPassword(Request $request, $token)
 {
     //some validation
     ...

     $password = $request->password;
     $tokenData = DB::table('password_resets')
     ->where('token', $token)->first();

     $user = User::where('email', $tokenData->email)->first();
     if ( !$user ) return redirect()->to('home'); //or wherever you want

     $user->password = Hash::make($password);
     $user->update(); //or $user->save();

     //do we log the user directly or let them login and try their password for the first time ? if yes 
     Auth::login($user);

    // If the user shouldn't reuse the token later, delete the token 
    DB::table('password_resets')->where('email', $user->email')->delete();

    //redirect where we want according to whether they are logged in or not.
 }

N'oubliez pas d'ajouter des itinéraires

Route::get('password-reset', 'PasswordController@showForm'); //I did not create this controller. it simply displays a view with a form to take the email
Route::post('password-reset', 'PasswordController@sendPasswordResetToken');
Route::get('reset-password/{token}', 'PasswordController@showPasswordResetForm');
Route::post('reset-password/{token}', 'PasswordController@resetPassword');

Note: Il pourrait y avoir des fautes de frappe ou des erreurs de syntaxe parce que je n'ai pas testé cela et l'ai écrit ici directement du haut de ma tête. Si vous voyez une erreur/exception, ne paniquez pas, lisez l'erreur et recherchez google.

18
EddyTheDove