Laravel Authenticate マルチ認証の流れを追ってみる

#Laravel認証の流れを追ってみる

今まで何の理解もせずに他の記事の見よう見まねをしてやってきたのですが、きちんと理解してみようと認証の流れを追ってみます:palm_tree:

初心者ですので間違いも多いかもしれませんが、教えてもらえると嬉しいです:woman:

#web.php
```
＊ 認証前ログイン画面
Route::get('admin/login','Admin\LoginController@showLoginForm')->name('show_admin_login_form');
Route::post('admin/login','Admin\LoginController@login')->name('admin_login');

＊ 認証後
Route::group(['middleware' => 'auth:admin'], function () {
    Route::get('admin/top/{id}', 'ItemController@top')->name('admin_top');
});
```

`'middleware' => 'auth:admin'`はKernel.php(App\Http)54行目辺りにあたる

```
 protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
```


#App\Http\Middleware\Authenticate

39行目辺りのhandleメソッドが実行される

```
public function handle($request, Closure $next, ...$guards)
    {
      　　$this->authenticate($request, $guards);
        return $next($request);
    }
```

`$request = array ()`
`$guards = array (0 => 'brand') `
でした。


次に`$this->authenticate`でhandleメソッドの下にある**authenticateメソッドへ**

```
 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);
            }
        }

        throw new AuthenticationException(
            'Unauthenticated.', $guards, $this->redirectTo($request)
        );
    }
```


ここで$guardsには` 0 => 'brand',`と配列が入っているのでforeachの中へ、`$guard = brand`でif文の中へ。
`$this->auth`は　Illuminate\Auth\AuthManagerのことなので、**AuthManagerへ**


#Illuminate\Auth\AuthManager

`if ($this->auth->guard($guard)->check())`で **AuthManegerのguardメソッドへ**

```
 public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();

        return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
    }
```


```
$name = $name ?: $this->getDefaultDriver();

↓ 

if($name) {
$name = $name
} else {
 $this->getDefaultDriver()
};

```
$name = nullなのでelseの
**getDefaultDriverメソッドへ**

```
 public function getDefaultDriver()
    {
        return $this->app['config']['auth.defaults.guard'];
    }
```

↓

**configディレクトリーのauth.phpファイルへ**

```
    'defaults' => [
        'guard' => 'user',
        'passwords' => 'users',
    ],
```
defaultsのguardは'user'となっているので


**AuthManageのguardへ戻る**

```
 public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();

        return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
    }
```

```
return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);

↓ 

??　は　$this->guards[$name]がなければその処理をスキップして
次の$this->guards[$name] = $this->resolve($name)へ

```

`protected $guards = [];`
`this->guards[$name]`がないので、??以降`$this->guards[$name] = $this->resolve($name)`へ


**resolveメソッド**

```
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."
        );
    }
```

`$config = $this->getConfig($name);`で下記getConfigメソッドからの戻り値で配列を受け取る。
`$config =  array (
  'driver' => 'session',
  'provider' => 'admins',
)  `
`$name = admin`

```
    protected function getConfig($name)
    {
        return $this->app['config']["auth.guards.{$name}"];
    }


** configディレクトリー　auth.php

    'guards' => [
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
```


`        if (method_exists($this, $driverMethod)) `で　methodがあるのでauth.phpのどれかを特定して物体？が返される


そこからやっと元の**App\Http\Middleware\Authenticate**に戻る
今までこのforeach内のguard()をやっていたので、
このguardは AuthManagerで　`$this->guards[$name] = $this->resolve($name`を戻されるので、

```
 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);
            }
        }

        throw new AuthenticationException(
            'Unauthenticated.', $guards, $this->redirectTo($request)
        );
    }
```

if内でまだログインしてないので、checkメソッドの戻り値の$this->userはnullとなり、`throw new AuthenticationException`でredirectToメソッドで記述したとおりのところに移動

```
protected function redirectTo($request)
{
    if (! $request->expectsJson()) {
        if ($request->path() === 'home') {
            return route('login');
        } elseif ($request->path() === 'admin/home') {
            return route('show_admin_login_form');
        }
    }
}

`Route::post('login',    'Admin\LoginController@login')->name('admin.login');`
```

**AdminControllerのlogin (AuthenticatesUsersのlogin)**

```
    public function login(Request $request)
    {
        $this->validateLogin($request);

           if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

          $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }
```

` $this->validateLogin($request);`で必要な文字数などが合っているか確認され
`if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }`
でLoginができる