Laravelでパスワードリセット機能を実装してみた

Laravel
スポンサーリンク

個人的に興味があり実装してみたのでメモとして残しておきます。

基本情報

PHPとLaravelのバージョンを記載しておきます。

  • PHP 7.2.261
  • Laravel Framework 5.5.48

パスワードリセット全体像

全体像をまとめてみました。

以下、パスワード忘れのシナリオ(妄想)

パスワード忘れてしまったーーー><

よし再発行するか、なになにまずはリンクをクリックする

次にメールアドレスを入力して送信ボタンを押下する

するとシステムがリセット用のメールを飛ばしてくれるみたいだ..

そのメールの中に記述されているURLをクリックすると、パスワードリセット画面に遷移する..

必要事項を入力して登録ボタンを押すとパスワードがリセットされる。(ほうほう)

(妄想終わり)

こんな感じのものを実装します。

見た目は図と異なります。※laravelのデフォルトのデザイン

テーブルの作成

テーブル作成に必要な材料(ユーザとパスワードリセット用のマイグレーションファイル)はLaravelのプロジェクトを作成した時点で用意されているので、以下のartisanコマンドを実行するだけで必要なテーブルを作成することが出来ます

※事前にDB作成と環境情報(envファイル)の書き換えを行っておいてください。

php artisan migrate

usersテーブルとpassword_resetsテーブルが作成されます。

Userモデルの作成

Userクラスはすでに用意されています。

このUserクラスにsendPasswordResetNotificationメソッドを追加してください。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
    
    /**
    * パスワードリセット通知の送信
    *
    * @param  string  $token
    * @return void
    */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPasswordNotification($token));
    }
}

通知を送信可能にするためにsendPasswordResetNotificationメソッドを追加しました。

Userクラスは親Userクラス(Illuminate\Foundation\Auth\User)を継承しております。

この親Userクラスが利用しているトレイト( CanResetPassword )の中に sendPasswordResetNotificationメソッドは定義されおり、これをオーバーライドしています。

ただし、このままだと件名や本文がデフォルト内容で送信されてしまいます。

それはちょっと・・・という方は、自身で通知クラスを作成しましょう。

通知クラスの作成

app/Notifications配下に ResetPassword というクラスを作成します。

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class ResetPassword extends Notification
{
    public $token;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($token)
    {
        $this->token = $token;
    }
    
    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
             ->subject('パスワード初期化についてのお知らせ')
             ->view('auth.users.emails.reset', [
                 'restUrl' => route('password.reset', [ 'token' => $this->token])
        ]);
    }
}

注目していただきたいのはtoMailメソッドです。

このメソッドの中で、件名の指定や通知メールにレンダリングするviewを指定しております。

詳しくはLaravelのドキュメントをご参照ください。

通知 5.4 Laravel

ついでなのでviewファイルも作成しちゃいましょう。

resources/views/auth/usersの中にemailsフォルダを作り、reset.blade.phpを生成しましょう。

<p>以下のURLをクリックし、パスワードの再設定を行って下さい。</p>
<p><a href='{{ $restUrl }}'>{{ $restUrl }}</a></p>

最後に通知クラスを適用します。

Userクラスを以下のように書き換えてください。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Notifications\ResetPassword;  //****追加****

class User extends Authenticatable
{

(省略)

    /**
    * パスワードリセット通知の送信
    *
    * @param  string  $token
    * @return void
    */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPassword($token)); //****変更****
    }
}

コントローラの作成

コントローラもすでに用意してあります。

パスワードリセットで利用するコントローラは、ForgotPasswordControllerとResetPasswordControllerになります。

必要な定義は揃っているので手を入れる必要はありません。

ビューの作成

以下のartisanコマンドを実行してください。

php artisan make:auth

必要なviewファイル( email.blade.phpとreset.blade.php )が生成されます。

すべて英語表記ですが、今回はこのまま使用します。

ルーターの設定

次にroutesの設定を行います。

routes/web.phpに以下に記述を加えてください。

//パスワードリセット
Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');

メールの基本設定

本記事ではgmailでメールを送信します。

.envファイルを以下のように書き換えてください。

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME={自身のメールアドレス}
MAIL_PASSWORD={アプリパスワード}
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS={自身のメールアドレス}
MAIL_FROM_NAME=demo-laravel-crud

アプリパスワードの発行方法は以下を参考にしてください

アプリ パスワードでログインする - Gmail ヘルプ
ヒント: アプリ パスワードは推奨されておらず、ほとんどの場合は不要です。アカウントの安全性を保つには、「Google でログイン」機能を使用して

書き換えが終わったら、以下のコマンドでキャッシュクリアすることを推奨します。

$ php artisan cache:clear

以上でパスワードリセット機能が実装できていると思います。

動かして学ぶ!Laravel開発入門 | 山崎 大助 | コンピュータ・IT | Kindleストア | Amazon
Amazonで山崎 大助の動かして学ぶ!Laravel開発入門。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。
PHPフレームワーク Laravel入門 第2版 | 掌田津耶乃 | 工学 | Kindleストア | Amazon
Amazonで掌田津耶乃のPHPフレームワーク Laravel入門 第2版。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。

さいごに

まだまだ勉強中の身なので、わかりにくい部分も多々あると思いますが大目にみてください。

引き続き学習していきます。

Laravel
スポンサーリンク
エンジニアの日記

コメント