以前書いた、Laravelのmiddleware authを理解したい (5.5)から、約2年経過しましたが、LTSも新バージョンが出ているので、差分を理解するという意味も含めて6.xについて調べてみることにしました。
例によって、Laravelのmiddleware authを理解したい と同じ構成です(感謝です!)
環境
Laravel 6.18.6 (laravel/framework のSHA: 4ef5f9612c2694c915f53f0cec3e4081e9bfc778)
調査
※ make:auth
artisanコマンドがなくなりました!
マニュアルより、
composer require laravel/ui "^1.0" --dev
php artisan ui vue --auth
とやることで、vue.jsを利用したスカルフォードが生成される。
自動生成コードによれば、認証が必要なものはMiddlewareで定義する。
Http/Controllers/HomeController.php
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
-
Http/Kernel.php
にて、「auth」というaliasを登録している。
Http/Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
\Illuminate\Auth\Middleware\Authenticate
でやっていること
- ガードを指定 することで、認証の方式を変更できる
\Illuminate\Auth\Middleware\Authenticate.php
public function handle($request, Closure $next, ...$guards)
{
$this->authenticate($request, $guards);
return $next($request);
}
- 上記の
$guards
に、指定された文字列が入る($this->middleware('auth:web.api');
のように複数指定が可能なので可変引数 -
Illuminate/Auth/AuthManager
で処理を行う -
interafce Illuminate\Contracts\Auth\Factory
が、DIされているが、下記の通り実態はAuthManager
\Illuminate\Auth\Middleware\Authenticate.php
// use Illuminate\Contracts\Auth\Factory as Auth; とされている
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/Illuminate/Foundation/Application.php
public function registerCoreContainerAliases()
{
foreach ([
'app' => [self::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
-
$guard
で指定された分だけ、Guardを使用して、認証済みか確認(/Illuminate/Auth/SessionGuard::check()
)し、認証済みのGuardの使用を宣言する - ここで、
config/auth.php
で指定がなかったguardsは、Exceptionが発生する - 指定可能なdriverは、「session」「token」とのことだが、ここでは省略
-
$guard
を指定していない場合は、nullとして処理され、AuthManagerで、config/auth.php
の、defaultsが指定される。初期設定ではweb → 本資料では、このパターンについて理解を進める
/Illuminate/Auth/SessionGuard::check()
が呼ばれるまで
呼んでいる箇所
/Illuminate/Auth/Middleware/Authenticate.php
protected function authenticate($request, array $guards)
{
if (empty($guards)) {
$guards = [null];
}
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
$this->auth->guard()
でオブジェクトが特定されるまで
/Illuminate/Auth/AuthManager.php
public function guard($name = null)
{
$name = $name ?: $this->getDefaultDriver();
return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
}
- 今回は
$name = null
のため、$name = 'session'
として処理
/Illuminate/Auth/AuthManager.php
protected function resolve($name)
{
$config = $this->getConfig($name);
if (is_null($config)) {
throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
}
if (isset($this->customCreators[$config['driver']])) {
return $this->callCustomCreator($name, $config);
}
$driverMethod = 'create'.ucfirst($config['driver']).'Driver';
if (method_exists($this, $driverMethod)) {
return $this->{$driverMethod}($name, $config);
}
throw new InvalidArgumentException(
"Auth driver [{$config['driver']}] for guard [{$name}] is not defined."
);
}
- AuthManage.php::resolve() で、使用するGuardを決定
AuthManager::createSessionDriver() で、Guardが生成される
/Illuminate/Auth/AuthManager.php
/**
* Create a session based authentication guard.
*
* @param string $name
* @param array $config
* @return \Illuminate\Auth\SessionGuard
*/
public function createSessionDriver($name, $config)
{
$provider = $this->createUserProvider($config['provider'] ?? null);
$guard = new SessionGuard($name, $provider, $this->app['session.store']);
- 実体は
/Illuminate/Auth/SessionGuard
AuthManager::createUserDriver()
でやっていること
(実装は、trait /Illuminate/Auth/CreateUserProviders
)
5.2解説より、
-
config/auth.php
の、auth.providers.{$provider}
の値 →auth.providers.users
の値を取得する- デフォルト:
auth.providers.users = ['driver'=>'eloquent','model'=>'App\User']
- デフォルト:
- 「何を使って、どこからUser情報を取得するか」というのを取得する。
- デフォルトでは、「eloquentを使って、App\Userモデルの情報をとる」ということ
- Laravelでは、driverに以下の設定が可能
-
eloquent
- Eloquent Modelを使ってユーザを特定
-
model
で、どのModelを使用するか指定 -
Illuminate\Auth\EloquentUserProvider
を使う
-
database
- データベースを使う
-
table
でテーブル名を指定 -
Illuminate\Auth\DatabaseUserProvider
を使う
-
-
interface Illuminate\Contracts\Auth\UserProvider
の主なメソッドは以下のとおり- retrieveById():IDで認証する
- retrieveByToken():token(remember me)で認証する
- updateRememberToken():token(remember me)を更新する
- retrieveByCredentials():credentialを更新する
- validateCredentials():credentialを利用してユーザを検証する
new SessionGuard()
でやっていること
Illuminate\Auth\SessionGuard.php
public function __construct($name,
UserProvider $provider,
Session $session,
Request $request = null)
{
$this->name = $name;
$this->session = $session;
$this->request = $request;
$this->provider = $provider;
}
SessionGuard::check()
でやっていること
trait \Illuminate\Auth\GuardHelpers
に実装
/**
* Determine if the current user is authenticated.
*
* @return bool
*/
public function check()
{
return ! is_null($this->user());
}
-
user()
を使って、認証されているかを返す
SessionGuard::user()
の処理
フレームワークの根幹に関わるところなので、基本的な処理は変わっていない印象です。(メソッド名とかクラス名が少し変わってるけど、流れは変わっていない)
参考になればと思います。