Laravel 5.1用户认证(二) —— 使用Laravel内置组件快速实现密码重置

忘记密码是应用中常见的场景之一,Laravel 5.1也提供了对密码重置的支持,我们只需稍微做一下配置即可轻松实现重置密码。

1、实现思路

通过给用户注册邮箱发送包含特定令牌的重置密码链接,然后用户登录邮箱通过访问该重置密码链接实现密码的重置。

2、数据表&模型

  • 实现CanResetPasswordContract契约并使用CanResetPasswordtrait的User模型(Laravel自带)
  • 用于存放重置密码令牌的表password_resets(Laravel自带该表对应迁移文件,上一节中已一并创建)

3、创建路由

Laravel自带了用于密码重置的控制器Auth\PasswordController,和上一节提到的AuthController位于统一目录下。重置密码相关的业务逻辑都是通过该控制器中使用的ResetsPasswordstrait来实现的。下面我们在routes.php中为重置密码定义相关路由规则:

// 发送密码重置链接路由
Route::get('password/email', 'Auth\PasswordController@getEmail');
Route::post('password/email', 'Auth\PasswordController@postEmail');

// 密码重置路由
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');

4、创建视图

定义好路由之后我们为get请求定义对应视图文件,首先创建发送密码重置链接路由对应视图resources/views/auth/password.blade.php

<form method="POST" action="/password/email">
    {!! csrf_field() !!}

    <div>
        Email
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        <button type="submit">
            发送密码重置链接
        </button>
    </div>
</form>

然后创建重置密码路由对应视图resources/views/auth/reset.blade.php

<form method="POST" action="/password/reset">
    {!! csrf_field() !!}
    <input type="hidden" name="token" value="{{ $token }}">

    <div>
        Email:<input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        新密码:<input type="password" name="password">
    </div>

    <div>
        确认密码:<input type="password" name="password_confirmation">
    </div>

    <div>
        <button type="submit">
            重置密码
        </button>
    </div>
</form>

此外我们还要创建一个额外视图——发送密码重置链接的邮件模板视图resources/views/emails/password.blade.php,用于为该邮件提供视图模板:

点击这里重置密码: {{ url('password/reset/'.$token) }}

如果该邮件模板视图文件路径位于其他地方,不要忘了配置config/auth.php中的password.email值与新路径对应。

5、发送邮件配置

接下来我们要做的是配置相关文件实现邮件发送功能为下一步测试做准备。

Laravel使用SwiftMailer库提供的邮件API实现邮件操作,详情可查看邮件文档,这里我们仅作简单配置实现邮件发送,邮件配置文件是config/mail.php

<?php

return [
    'driver' => env('MAIL_DRIVER', 'smtp'),
    'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
    'port' => env('MAIL_PORT', 587),
    'from' => ['address' => null, 'name' => null],
    'encryption' => env('MAIL_ENCRYPTION', 'tls'),
    'username' => env('MAIL_USERNAME'),
    'password' => env('MAIL_PASSWORD'),
    'sendmail' => '/usr/sbin/sendmail -bs',
    'pretend' => false,
];

可见大部分配置在.env文件中设置,这里我的.env文件配置如下:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.163.com
MAIL_PORT=25
MAIL_USERNAME=yaojinbu@163.com
MAIL_PASSWORD=mypassword
MAIL_ENCRYPTION=null

我使用的是163邮箱,其它邮箱参考对应邮箱相关设置项,并将自己的账户信息填写到MAIL_USERNAMEMAIL_PASSWORD

此外我们还要配置mail.php中的from配置如下:

'from' => ['address' => 'yaojinbu@163.com ', 'name' => 'Laravel学院'],

这里只需要将address.env文件中的MAIL_USERNAME值相匹配即可。至于name值就是邮箱中发件人名称,可自定义。

做好这一步配置后,接下来即可测试密码重置了。

6、重置密码

在浏览器中访问http://laravel.app:8000/password/email,页面显示如下:

Laravel 发送重置密码邮件

在Email输入框中填写你的注册邮箱,点击“发送密码重置链接”,然后去邮箱中查看收件箱,如果发送成功,可收到一封内容如下的密码重置邮件:

点击这里重置密码: http://laravel.app:8000/password/reset/96c652e4885591c7ecfcb4f1ecc6f9b877ac1a2ab445e7fb45a89fdfc7283585

此时数据表password_resets中也新增了一条记录,用于保存重置链接令牌:

Laravel保存重置密码token

该令牌默认保存一个小时,要修有效期,可通过编辑config/auth.phppassword.expire来实现。

我们将重置密码邮件中的链接拷贝出来粘贴到浏览器地址栏回车,页面显示内容如下:

Laravel重置密码页面

填写该表单后点击重置密码按钮即可完成密码重置。

密码重置成功后,默认跳转链接为/home,我们可以在PasswordController中通过设置$redirectTo/$redirectPath属性的值修改该跳转链接:

protected $redirectPath = '/profile';

这样重置成功后会跳转到http://laravel.app:8000/profile

test登录成功!

同时password_resets中的对应记录也会被删除。

好了,下次登录就可以使用新密码进行登录认证了。

学院君

学院君 has written 548 articles

资深PHP工程师,Laravel学院院长