Edited at

Laravel で認証パラメータを追加する

More than 1 year has passed since last update.

Laravel の認証は php artisan make:auth である程度のログイン機能が吐き出されて、あとはビューをちょちょいと変更したり Route 周りを自分の好みにカスタマイズしたりで非常に強力な認証が最小限の工数で利用できます。

しかしながら融通が効きにくいこともあり、例えばメールアドレス、パスワード以外の有効無効フラグを追加したいのだが、というときに公式ではこう記載されています。


<?php

namespace App\Http\Controllers;

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

class LoginController extends Controller
{
/**
* 認証を処理する
*
* @param \Illuminate\Http\Request $request
*
* @return Response
*/

public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');

if (Auth::attempt($credentials)) {
// 認証に成功した
return redirect()->intended('dashboard');
}
}
}

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {

// ユーザーは存在しており、かつアクティブで、資格停止されていない
}

しかし、App\Http\Auth\LoginContoller.php の実態たる Illuminate\Foundation\Auth\AuthenticatesUsers ではこんな記述はでてきません。

そこでLaravel5.4のmake:auth再利用でハマったを参考にしてどうすればフラグを認証判定に含めることができるかを調べてみました。

例のごとく結論を知りたい方は末尾へどうぞ。

ここでは有効・無効のフラグを active ではなく is_valid としています。


調査

参考元のサイトを踏まえて追って行くと、

Illuminate\Auth\SessionGuard.php の attempt メソッドにたどり着きます。


Illuminate\Auth\SessionGuard.php


public function attempt(array $credentials = [], $remember = false)
{
$this->fireAttemptEvent($credentials, $remember);

$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

if ($this->hasValidCredentials($user, $credentials)) {
$this->login($user, $remember);

return true;
}

$this->fireFailedEvent($user, $credentials);

return false;
}


retrieveByCredentials($credentials)hasValidCredentials($user, $credentials) の実体が Illuminate\Auth\EloquentUserProvider.php とのことなので確認。


Illuminate\Auth\EloquentUserProvider.php


public function retrieveByCredentials(array $credentials)
{
if (empty($credentials) ||
(count($credentials) === 1 &&
array_key_exists('password', $credentials))) {
return;
}

$query = $this->createModel()->newQuery();

foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}

return $query->first();
}

public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];

return $this->hasher->check($plain, $user->getAuthPassword());
}


retrieveByCredentials を確認すると、where でちゃんとパラメータが渡せるようになっていますね。

となると、key value 型の配列を $credentials に入れてあげれば良い。

$credentials が設定されているところは LoginController.php の継承元 Illuminate\Foundation\Auth\AuthenticatesUsers にあります。


Illuminate\Foundation\Auth\AuthenticatesUsers.php


/**
* Get the needed authorization credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/

protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}

$request->only を var_dump してみると、


array (size=2)
'email' => string 'xxxxx@xxxxxx.xxxxx' (length=xx)
'password' => string 'ABCDEFGH' (length=8)

という、素直な配列です。

ではコレに追加してやるだけですね。


結論


App\Http\Auth\LoginContoller.php


use Illuminate\Http\Request;

protected function credentials(Request $request)
{
$temporary = $request->only($this->username(), 'password');
$temporary['is_valid'] = 1;

return $temporary;
}


というわけで、is_valid は boolean 型ですので、1 なり true なりを渡してやるようにすれば、$credentials に追加することができ、DBの検索時 where に追加されるようになりました。