6/21 13:22 最終更新完了です。
Laravelの認証の仕組みを利用することは、公式ドキュメントや色々な記事を読むことで可能になりましたが、
「じゃあ実際どういう仕組みで認証してるんだろう」という疑問にぶち当たり、調べて見ました。
Laravelのmiddleware authを理解したい
こちらの記事のLaravel5.5版です。構成も丸パクリさせていただいています。
環境
Laravel 5.5
PHP 7.0
MacOSX 10.13
調査
php artisan make:auth
で自動生成されたコードによれば、認証が必要なものはMiddlewareで定義する。
class HomeController extends Controller
{
    //コンストラクタ
    public function __construct()
    {
        $this->middleware('auth');
    }
・Http/Kernel.phpにて「auth」というaliasを登録している
Http/Kernel.php
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
※ 5.5〜 Framework内のクラスを利用するように変更された(らしい)
\Illuminate\Auth\Middleware\Authenticate でやっていること
- handleが定義されている(自明ですかね)
 - 
ガードを指定することで、認証の方式を変更できる
- $guards に指定された文字列が入る(
$this->middleware('auth:web,api');のように複数指定が可能なので配列) 
 - $guards に指定された文字列が入る(
 - $guardsが指定されていないときは、\Illuminate\Auth\AuthManager\authenticate() を呼ぶ → 本資料はこちらについてだけ理解を進める
- 実装は 
interface Illuminate\Contracts\Auth\Factoryだが、実際にDIコンテナに登録されているのは上のクラス(\Illuminate\Foundation\Application\registerCoreContainerAliases()) 
 - 実装は 
 
\Illuminate\Auth\AuthManager\authenticate() が呼ばれるまで
- \Illuminate\Auth\AuthManager\authenticate() はコード上存在しないです。
 
\Illuminate\Auth\AuthManager.php
    public function __call($method, $parameters)
    {
        return $this->guard()->{$method}(...$parameters);
    }
$this->guard() でオブジェクトが特定されるまで
Illuminate\Auth\AuthManager.php
    public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();
        return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
    }
- $this->resolve() で解決している模様
 - $nameは、"web"(デフォルト: auth.default.web)
 
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 guard driver [{$name}] is not defined.");
    }
- $config['driver'] は、config/auth.php で定義しているdriverが読み込まれる。
- デフォルトのままだと'session'
 
 - 
$driverMethod = 'createSessionDriver'で話を進める 
Illuminate\Auth\AuthManager.php
    public function createSessionDriver($name, $config)
    {
        $provider = $this->createUserProvider($config['provider'] ?? null);
        $guard = new SessionGuard($name, $provider, $this->app['session.store']);
        // When using the remember me functionality of the authentication services we
        // will need to be set the encryption instance of the guard, which allows
        // secure, encrypted cookie values to get generated for those cookies.
        if (method_exists($guard, 'setCookieJar')) {
            $guard->setCookieJar($this->app['cookie']);
        }
        if (method_exists($guard, 'setDispatcher')) {
            $guard->setDispatcher($this->app['events']);
        }
        if (method_exists($guard, 'setRequest')) {
            $guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
        }
        return $guard;
    }
- SessionGuard が、guardクラス
 
createUserProviderでやっていること
↓ 5.2解説より (同じ模様)
- configのauth.providers.{$provider}の値 → auth.providers.usersの値を取得する
- デフォルト:auth.providers.users = ['driver'=>'eloquent','model'=>'App\User']
 
 - 「何を使って、どこからUser情報を取得するか」というのを取得する。
 - デフォルトでは、「eloquentを使って、App\Userモデルの情報をとる」ということ
 
本稿の追記
- Laravelで用意されているUserProviderは以下
- auth.providers.users.driver = 'eloquent'の場合は、Illuminate\Auth\EloquentUserProvider
 - 'database'の場合は、Illuminate\Auth\DatabaseUserProvider
 
 - 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;
    }
- セッションやリクエストのセットを行っている
 - 5.2と同じ模様
 
SessionGuard::authenticate() でやっていること
- authenticate() メソッドは Illuminate\Auth\GuardHelper に存在(use で読み込まれている)
 
GuardHelper.php
    public function authenticate()
    {
        if (! is_null($user = $this->user())) {
            return $user;
        }
        throw new AuthenticationException;
    }
user() がやっていること
- GuardHelperの$this->userは、SessionGuard に実装されている(戻った)
 - $this->loggedOut = true だったらnullを返す
- logout() で trueがセットされる。ログアウトしたけどSessionが残っているのを防ぐ模様
 
 - $this->user が存在していれば、それを返す
- DBアクセスを減らす目的
 - これに該当することってあるんですかね?
 
 - SessionからIDを取得
- Sessionについては別記事でまとめる
 
 
        $id = $this->session->get($this->getName());
- IDが取れたら、UserProviderのretriveByIdで、Userオブジェクトを取得する
- 取得できたら認証完了のイベント通知を行う
 
 - 
$recaller = $this->recaller()で、Recallerオブジェクト生成- "remember me" Cookieの情報を保持する
 - 情報がない場合はnull
 
 - ここまでで
$this->userがとれていなくて、$recallerが存在している場合、Recallerから$this->userの取得を試みる - 最後にログインユーザが取れていれば
$this->user、取れていなければnull(ログインなし)を返す 
以上です。