重置密码

未匹配的标注

重置密码

介绍

大多数Web应用程序都会为用户提供重置密码的功能。 Laravel 已经提供了便捷的服务来发送密码重置链接和安全重置密码,而不需要您为每个应用程序重新实现此功能。

技巧:想快速上手? 在新的 Laravel 应用程序中安装 Laravel 入门套件。 Laravel 入门套件会为您搭建完整的身份验证系统, 包括重置密码功能。

模型准备

在使用 Laravel 的重置密码功能之前,确认 App\Models\User 模型已经使用了 Illuminate\Notifications\Notifiable 性状。 通常,在新创建的 Laravel 应用程序的 App\Models\User 模型中默认引入了该性状。

接下来,验证 App\Models\User 模型是否继承了 Illuminate\Contracts\Auth\CanResetPassword 接口。
框架中包含的 App\Models\User 模型默认继承了此接口,并使用 Illuminate\Auth\Passwords\CanResetPassword 性状来实现了接口中的方法。

数据库准备

必须创建一个表来存储应用程序的重置密码的令牌。 Laravel 应用程序中,默认包含了此表的迁移,因此,您只需执行以下命令即可创建此表:

php artisan migrate

路由

为了正确实现允许用户重置密码的支持,我们需要定义几个路由。首先,我们需要一对路由来处理,允许用户通过电子邮件地址请求密码重置链接。第二,一旦用户访问通过电子邮件发送给他们的密码重置链接并完成密码重置表单,我们将需要一对路由来处理实际重置密码请求。

请求密码重置链接

密码重置链接请求表单

首先,我们将定义请求密码重置链接所需的路由。首先,我们将定义一个路由,该路由使用密码重置链接请求表单返回一个视图:

Route::get('/forgot-password', function () {
    return view('auth.forgot-password');
})->middleware('guest')->name('password.request');

此路由返回的视图应该有一个包含“email”字段的表单,该字段允许用户请求给定电子邮件地址的密码重置链接。

处理表单提交

接下来,我们将定义一个路由,该路由将从“忘记密码”视图处理表单提交请求。此路由将负责验证电子邮件地址并将密码重置请求发送给相应用户:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

Route::post('/forgot-password', function (Request $request) {
    $request->validate(['email' => 'required|email']);

    $status = Password::sendResetLink(
        $request->only('email')
    );

    return $status === Password::RESET_LINK_SENT
                ? back()->with(['status' => __($status)])
                : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');

在继续之前,让我们更详细地检查一下这条路由。首先,验证请求的 email属性。接下来,我们将使用 Laravel 内置的 Password 门面向用户发送一个密码重置链接。密码代理将负责按给定字段(在本例中是电子邮件地址)检索用户,并通过Laravel的内置消息通知系统 向用户发送密码重置链接。

sendResetLink 方法返回一个状态标识。可以使用Laravel的 本地化 助手来转换此状态,以便向用户显示有关请求状态的用户友好提示。密码重置状态的转换由应用程序的resources/lang/{lang}/passwords.php语言文件确定。状态slug的每个可能值的条目位于 passwords 语言文件中。

您可能想知道,在调用 Password 门面的 sendResetLink 方法时,Laravel 怎么知道如何从应用程序数据库中检索用户记录。Laravel密码代理利用身份验证系统的“用户提供者”来检索数据库记录。密码代理使用的用户提供程序是在 config/auth.php 配置文件的 passwords 配置数组中配置的。要了解有关编写自定义用户提供程序的更多信息,请参阅身份验证文档

技巧:当手动实现密码重置时,您需要自己定义视图和路由的内容。如果您想要包含所有必要的身份验证和验证逻辑的脚手架,请查看Laravel application starter kits.

重置密码

重置密码表单

接下来,我们将定义用户点击重置密码邮件中的链接,进行重置密码所需要的一些路由。第一步,先定义一个获取重置密码表单的路由。这个路由需要一个 token 来验证请求:

Route::get('/reset-password/{token}', function ($token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');

通过路由返回的视图应该显示一个含有 email 字段, password 字段, password_confirmation 字段和一个隐藏的值通过路由参数获取的 token 字段。

处理表单提交的数据

当然,我们需要定义一个路由来接受表单提交的数据。这个路由会检查传过来的参数并更新数据库中用户的密码:

use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;

Route::post('/reset-password', function (Request $request) {
    $request->validate([
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|min:8|confirmed',
    ]);

    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function ($user, $password) use ($request) {
            $user->forceFill([
                'password' => Hash::make($password)
            ])->save();

            $user->setRememberToken(Str::random(60));

            event(new PasswordReset($user));
        }
    );

    return $status == Password::PASSWORD_RESET
                ? redirect()->route('login')->with('status', __($status))
                : back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');

在继续之前,我们再详细地检查下这条路由。 首先,验证请求的tokenemailpassword 属性。 接下来,我们将使用 Laravel 的内置 “password broker”(通过 Password 门面)来验证密码重置。

如果提供给密码代理的令牌、电子邮件地址和密码有效,则将调用传递给 reset 方法的闭包。 在这个接收用户实例和纯文本密码的闭包中,我们可以更新数据库中用户的密码。

reset 方法返回一个 “状态” 标识。 此状态可以使用 Laravel 的 localization 助手进行翻译,以便向用户显示有关其请求状态的友好提示。 密码重置状态的翻译由您的应用程序的resources/lang/{lang}/passwords.php 语言文件决定。 状态标识的每个可能值的条目位于 passwords 语言文件中。

在继续之前,您可能想知道 Laravel 如何在调用 Password 门面的 reset 方法时知道如何从应用程序的数据库中检索用户记录。 Laravel 密码代理利用您的身份验证系统的 “user providers” 来检索数据库记录。 密码代理使用的用户提供程序在你的 config/auth.php 配置文件的 passwords 配置数组中配置。 要了解有关编写自定义用户提供程序的更多信息,请参阅 身份验证文档

自定义

重置链接自定义

您可以使用 ResetPassword 通知类提供的 createUrlUsing 方法自定义密码重置链接 URL。 此方法接受一个闭包,该闭包接收正在接收通知的用户实例以及密码重置链接令牌。 通常,您应该从 App\Providers\AuthServiceProvider 服务提供者的 boot 方法中调用此方法:

use Illuminate\Auth\Notifications\ResetPassword;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    ResetPassword::createUrlUsing(function ($user, string $token) {
        return 'https://example.com/reset-password?token='.$token;
    });
}

重置邮件自定义

您可以轻松修改用于向用户发送密码重置链接的通知类。 首先,覆盖您的 App\Models\User 模型上的 sendPasswordResetNotification 方法。 在此方法中,您可以使用您自己创建的任何 通知类 发送通知。 密码重置 $token 是该方法收到的第一个参数。 你可以使用这个 $token 来构建你选择的密码重置 URL 并将你的通知发送给用户:

use App\Notifications\ResetPasswordNotification;

/**
 * 发送密码重置通知给用户
 *
 * @param  string  $token
 * @return void
 */
public function sendPasswordResetNotification($token)
{
    $url = 'https://example.com/reset-password?token='.$token;

    $this->notify(new ResetPasswordNotification($url));
}

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
贡献者:9
讨论数量: 0
发起讨论 只看当前版本


暂无话题~