Laravelのログイン機能の認証処理のカスタマイズ(emailカラムとpasswordカラム以外で認証する)




<h2>イントロ</h2>
Laravelのログイン機能を実装するぞ！！！！！

* メールアドレス
* パスワード

**上記の項目で認証を行うのが定番だけど、これらを変えたいからカスタマイズする！**

* **ユーザーコード**
* パスワード(**`password`カラムじゃないパスワードを管理しているカラムから参照したい！**)

フォームから入力されたこれらの値でな！

というのがこの記事のざっくりとした内容です。

働いている現場によっては下記のようなことを言われることがあります。

* メールアドレスじゃないのをログイン時には使いたいからメールアドレス以外でログインできるようにしたい

* ユーザーテーブルのパスワードは`password`って名前のカラムで管理してなくて、`hoge_password`ってカラムで管理する

…ということがあるので備忘録として残します。
~~私自身が仕事でやるのに方法が見つからなくてすごい焦った~~

「そんなこと簡単にできるのか？」と思いましたが、やってみたら結構簡単でした！

<h2>バージョン</h2>

Laravel Framework 11.7.0

<h2>認証の流れの基本</h2>
ここではカスタマイズの前にLaravelの認証処理の基本的な動きを紹介しています。

「そんなのわかってるわ！」って人は飛ばして大丈夫です。

Authファザードの`attempt`メソッドを使って認証を行うのが基本ですね。
`attempt`メソッドは引数としてキー/値のペアで配列を受け取ります。
```php:LoginController.php
if(Auth::attempt([
    'email' => 'hogehoge@example.com',
    'password' => 'hogehogeYeah'    // ハッシュ化しなくても大丈夫
])) {
    // 認証成功後の処理を記載する
}
```
`users`テーブルのemailカラムの値(メールアドレス)を持っているユーザーがいるか確認し、そのメールアドレスを持つユーザーの`password`カラムの値(パスワード)が合っているのか確認する。
…というのが認証の流れですが、そこを変更したいので変更します。

<h2>認証時の条件で`email`カラムの値から確認するのを変更する</h2>
メールアドレスを変更したい場合ははっきり言って超がつくほど楽勝です。

単純に、キー名を変えたらいいだけです。

```php:LoginController.php
if(Auth::attempt([
    'user_code' => '9ka11djhUs_20',
    'password' => 'hogehogeYeah'    // ハッシュ化しなくても大丈夫
])) {
    // 認証成功後の処理を記載する
}
```
この例では`attempt`メソッドが`users`テーブルの`user_code`カラムで『9ka11djhUs_20』の値を持っているレコードを見に行って、その`password`カラムのパスワードが合っているかを確認してくれます。

<h2>認証時の条件でpasswordカラムの値から確認するのを変更する</h2>
パスワードはちょっと手間がかかる部分です。


attemptメソッドを呼び出す時は実は`SessionGuard`の`attempt`メソッドを呼び出しています。
https://github.com/laravel/framework/blob/10.x/src/Illuminate/Auth/SessionGuard.php#L377

その後に、パスワード認証等は`EloquentUserProvider`で行っているのですが、パスワードのキーは`password`で固定になっているそうです。
https://github.com/laravel/framework/blob/10.x/src/Illuminate/Auth/EloquentUserProvider.php#L151

`users`テーブルのパスワードを管理しているカラムが`password`という名前ではない場合は、`Authenticatable`を継承している`User`モデルクラスでオーバーライドして別のカラム名を設定する必要があります。

```php:LoginController.php
if(Auth::attempt([
    'user_code' => '9ka11djhUs_20',
    'password' => 'hogehogeYeah'    // ハッシュ化しなくても大丈夫
])) {
    // 認証成功後の処理を記載する
}
```

このにすることでパスワードは`hash_pass`カラムの値を見てくれるようになります。

```php:User.php
class User extends Authenticatable
{
    /**
    *
    * 認証時にUserテーブルのpasswordカラムではなく
    * hash_passカラムを使うためオーバーライドする
    * @return string
    */
    public function getAuthPassword(): string
    {
        return $this->hash_pass;
    }
}
```
この例では`attempt`メソッドが`usersテ`ーブルの`user_code`カラムで『9ka11djhUs_20』の値を持っているレコードを見に行って、オーバーライドしたことによりそのレコードの`hash_pass`カラムで管理しているパスワードが合っているかを確認してくれます。

<h3>注意点</h3>

[公式ドキュメントより](https://laravel.com/docs/9.x/authentication#authenticating-users)

> フレームワークは、データベース内のハッシュ化されたパスワードと比較する前に、値を自動的にハッシュするため

認証時でパスワードはハッシュ化した値を確認してくれるので、もしオーバーライドして`password`以外のカラムにした場合もそのカラムではハッシュ化した値を管理するようにしてください。

<h2>参考文献</h2>

* [公式ドキュメント](https://laravel.com/docs/9.x/authentication#authenticating-users)

* [Laravel ログイン認証に使用する項目を変更する](https://qiita.com/idylwork/items/fee405d9a711609337e2#password%E4%BB%A5%E5%A4%96%E3%81%AE%E5%80%A4%E3%82%92%E8%AA%8D%E8%A8%BC%E3%81%AB%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)

* [Laravel の Guard（認証） って実際何をやっているのじゃ？](https://qiita.com/tomoeine/items/40a966bf3801633cf90f#guard%E3%82%AF%E3%83%A9%E3%82%B9-%E3%81%AF%E4%BD%95%E3%82%92%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%98%E3%82%83)