#Laravel認証の流れを追ってみる
今まで何の理解もせずに他の記事の見よう見まねをしてやってきたのですが、きちんと理解してみようと認証の流れを追ってみます
初心者ですので間違いも多いかもしれませんが、教えてもらえると嬉しいです
#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ができる