Laravel API Resetting and Forgot Password
参考Auth文件夹内已经有的ForgotPasswordController和ResetPasswordController两个类文件。
为了方便我们直接先复制这两个文件:
粘贴到Api文件夹内:
将两个类文件的namespace修改为:
namespace App\Http\Controllers\Api;
当忘记密码时,我们需要的主要是在SendsPasswordResetEmails这个trait中的sendResetLinkEmail方法。
所以我们在api.php中添加一个route,用于将重置请求指引到该方法即可;
Route::post('/password/email', 'Api\ForgotPasswordController@sendResetLinkEmail');
同样的重置密码请求时,需要的是ResetsPasswords这个trait中的reset方法。
所以我们在api.php中添加一个route,用于将重置请求指引到该方法即可;
Route::post('/password/reset', 'Api\ResetPasswordController@reset');
注意:如果需要重写两个trait中的方法,比如我们的api请求需要一个json返回{Laravel 7.x版本已经支持判断返回json结果},可以在ForgotPasswordController和ResetPasswordController两个类文件中分别Ctrl+o快捷键重写即可。
用PostMan测试一下:
env中设置使用log,这样我们不用发送邮件,而是直接在laravel.log文件中查看发送的邮件信息。
PostMan点击send后:
发送了重置邮件。
不过发送了之后,我们没有自定义发送成功通知给api请求者。最好是自定义一个消息提示用户,请求发送了,请检查你的邮箱。
上面的重置邮件是系统提供的默认邮件。如果需要自定义模板,参考:自定义密码重置邮件
你可以轻松地修改用于向用户发送密码重置链接的通知类。首先,重写 User 模型中的 sendPasswordResetNotification 方法。 在此方法中,你可以使用任何你所选择的通知类来发送通知。该方法接收的第一个参数是密码重置令牌 $token :
/** * 发送密码重置通知。 * * @param string $token * @return void */ public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token)); }
原理是:其实就是重写
User基类中的CanResetPassword trait内部的sendPasswordResetNotification方法;
我们创建一个notification来自定义:
执行:
php artisan make:notification testPasswordResetEmailNotification
然后User模型类内重写sendPasswordResetNotification方法:
public function sendPasswordResetNotification($token) { $this->notify(New testPasswordResetEmailNotification($token)); }
由于testPasswordResetEmailNotification中传入了一个参数,所以testPasswordResetEmailNotification类需要修改一下构造函数。
然后把传入的参数存储一下,这个token值可以设置为公共,因为外部可能需要使用到。
由于发送的是邮件,所以我们需要定义一下邮件的内容。
如果没有头绪可以参考一下默认的:
这里修改示例如下:
/** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $urlToResetForm = config('app.url') . '/vue/reset-password-form/?' . $this->token; return (new MailMessage) ->subject(Lang::get('Test Reset Password Notification')) ->line(Lang::get('You are receiving this email because we received a password reset request for your account.')) ->action(Lang::get('Reset Password'), $urlToResetForm) ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.' . config('auth.defaults.passwords') . '.expire')])) ->line(Lang::get('If you did not request a password reset, no further action is required. Token: ==>' . $this->token)); }
再次用PostMan发送重置请求:
laravel.log文件中结果如下:
由于上面的urlToResetForm route 路由和前端页面我们没有给出,所以重置请求就直接用PostMan发送请求的方式代替。
重置的逻辑我们是通过访问
Route::post('/password/reset', 'Api\ResetPasswordController@reset');
交给ResetPasswordController中 ResetsPasswords这个trait内的reset方法。
查看方法内部,对请求的验证规则
所以我们的请求中必须包含token,email,password三个字段。
复制laravel.log【模拟邮件】中的token,我们请求的email和设置的新password,通过PostMan发送post请求至
http://laravelauth.test/api/password/reset
然后我们测试新密码登录:
注意这里返回token,是因为我之前用passport自定义了一个AuthController在login之后返回一个Personal Access Token。登录成功就会返回这个token,所以修改成功!