Laravel 8.xからパスワード入力に対するバリデーションが使いやすくなりました。
そこで、実際に使ってみながら試してみました。
パスワードの入力ルールを作成する
Laravel 8.xのパスワードのバリでションについては、日本語のドキュメントではこちらになります。
Illuminate\Validation\Rules\Password
に対してメソッドがいくつか用意されているので、それを利用しつつPHPのメソッドチェーンの形で定義をしていきます。ただし、Passwordクラスの中身を読むと、staticなメソッドはmin()のみっぽいので、Password::min(size)
から始めないといけなそうです。(後に説明するdefault
を除いて)
メソッド | 内容 |
---|---|
min(size) | 最低$size 文字以上必要 |
mixedCase() | 大文字と小文字が1文字ずつ必要 |
letters() | 最低1文字の文字が必要 |
number() | 最低1文字の数字が必要 |
symbols() | 最低1文字の記号が必要 |
uncompromised($threshold = 0) | パスワードのデータ漏えいがないことを確認 |
メソッドチェーンの利用方法として、以下のように必要なルールをつなげて書きます。
Password::min(8) ->letters() ->mixedCase() ->numbers() ->symbols() ->uncompromised()
これを利用することで例えば、8文字以上の大文字小文字と数字と記号を利用したパスワードじゃないといけない、のようなものが簡単につくれますね。
入力確認用パスワードのチェック(confirmed)
Webサイトのパスワード入力するページは、よくパスワードと確認用にもう一度入力するフォームがあるかと思います。これをチェックするためにconfirmed
というルールを利用すると楽です。
これは、そのパラメータが{field}_confirmation
と同じであることを確認するというものです。
例えば、以下のようなバリデーションを作ってみます。
$request->validate([ 'password' => [ 'required', 'confirmed', Password::min(8) ->mixedCase() ->numbers(), ], ]);
これはpasswordというパラメータのみしかチェックしてないように見えるのですが、実はpassword
がpassword_confirmation
と同じかどうかを確認しています。
$this->post('/password', [ 'password' => $password, 'password_confirmation' => $password_confirmation, ]);
イメージ、上記のようなリクエストパラメータです。
ここで気をつけないといけないのが、password_confirmation
ではなく、password_confirm
のようにリクエストパラメータ名を変えられないところです。
アプリケーション共通のパスワードルール
最近マージされた機能で、共通のパスワードルールを作成することができるようになりました。ドキュメントでいうデフォルトパスワードルールの定義と表現されているものです。バージョンは8.78.0以降利用可能です。
きっと一般的なWebサイトは、パスワードの入力をするAPIは1つではないと思います。例えば、新規登録時のパスワード入力とパスワードを忘れたときのパスワードの入力、のように、複数のURLでパスワードのリクエストを受け取る可能性があります。
各Controllerで毎回同じパスワードルールを定義するのはめんどくさいものです。ルールを変えたくなったらすべてのバリデーションのルールを変えるのは漏れが発生しそうです。
そこで、デフォルトパスワードルールを利用します。
$request->validate([ 'password' => [ 'required', 'confirmed', Password::min(8) ->mixedCase() ->numbers(), ], ]);
この例でやってみたいと思います。
AppServiceProvider
のboot()
に以下の処理を追加します。
public function boot() { Password::defaults(fn() => Password::min(8) ->mixedCase() ->numbers()); }
Passwordのdefaults()というメソッドにコールバック関数を渡してルールを定義しています。
Controllerに書いているバリデーションルールを以下のように書き換えます。
$request->validate([ 'password' => [ 'required', 'confirmed', Password::default(), ], ]);
Passwordのdefault()を呼んでいるだけです。これだけで、置き換え完了です。
こうすることで、新規登録時の入力チェックとパスワードの再設定時の入力チェックのそれぞれの処理はPassword::default()と書いておき、AppServiceProvider側でルールを調整するだけで、全てのルールを変更することが可能になりメンテナンス性が向上しますね。
また、Passwordクラスの中身を読むと、required()
やsometimes()
があるので、requiredやsometimesをバリデーションルール側に書く必要がなくなりそうです。
/** * Get the default configuration of the password rule and mark the field as required. * * @return array */ public static function required() { return ['required', static::default()]; } /** * Get the default configuration of the password rule and mark the field as sometimes being required. * * @return array */ public static function sometimes() { return ['sometimes', static::default()]; }
最後に
以上のような便利な機能を利用すれば、各Controllerの開発時のパスワードの入力チェック処理は以下のように、パスワードルールを気にせずシンプルな書き方をするだけになります。
$request->validate([ 'password' => [ 'confirmed', Password::required(), ], ]);
パスワードルールを変更したいときだけ、ルールが書かれているAppServiceProviderを調整すれば良いだけになり、実装者は普段の開発ではパスワードルールを気にする必要がなくなりそうですね。