Laravel

Laravelのmiddleware authを理解したい

More than 1 year has passed since last update.


環境

Laravel 5.2

PHP 7.0

ubuntu14.04


目的

Laravelのmiddlewareのauthを理解する

※middlewareのauthは、ログイン状態のチェックを行うもので、ログイン処理ではないので注意

※ログイン処理は、Illuminate\Foundation\AuthのAuthenticatesUsersを調査すべし


調査


  • middlewareの使い方は、route.phpにRoute::groupで指定する


route.php

  Route::group(['middleware' => ['auth']], function () {

// この中はログインされている場合のみルーティングされる
Route::get('/', function () {
return view('dashboad');
});
});


  • Http/Kernel.phpにて「auth」というaliasを登録している


Http/Kernel.php

protected $routeMiddleware = [

'auth' => \App\Http\Middleware\Authenticate::class,


\App\Http\Middleware\Authenticateでやってること


  • handleが定義されている(middlewareはこのhandleメソッドが呼ばれる)

  • 認証は、Auth::guard($guard)->guest()が行っているようだ。

  • 認証NGならログインへリダイレクトしている

  • 認証OKならreturn $next($request);



    • $nextは、本来のrouteが設定される(たとえば/とか)と理解。




前半 (Auth::guard($guard)->guest()Auth::guard()部分)


Auth::guard($guard)がやってること


  • ソースファイル:vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php


\Illuminate\Auth\AuthManager.php

    /**

* Attempt to get the guard from the local cache.
*
* @param string $name
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/

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

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



  • $nameがnullの場合、getDefaultDriver()がコールされ、configのauth.defaults.guardの値(デフォルトは'web')がセットされる

  • return値は三項演算子で求められる


  • $this->guards['web']のissset()がfalseの場合、$this->resolve($name)を実行する


  • $this->resolve($name)取得した$gurad(↓resolveを参照)を返す。


resolve($name)がやってること


  • まず、configのauth.guards.{$name}の値。すなわち、→ auth.guards.webの値を取得する


    • デフォルト:auth.guards.web = ['driver'=>'session','provider'=>'user']




  • 'create'.ucfirst($config['driver']).'Driver';でdriverMethodを生成。


    • driverは「session」なので、 createSessionDriver()となる



  • createSessionDriver()メソッドの実行し、返り値をreturn


createSessionDriver()がやってること


  • createSessionDriver()はAuthManagerクラスにある

  • createUserProvider()を呼び出し、Provider情報を取得(↓createUserProvider参照)

  • SessionGuard()をnew(↓)


    • $guard = new SessionGuard($name, $provider, $this->app['session.store']);



  • $guradにIlluminate\Cookie\CookieJar(暗号化用クッキーの設定?)をセット

  • $guradにIlluminate\Events\Dispatcher(イベントのListen情報)をセット

  • $guradにIlluminate\Http\Request(リクエストパラメータ)をセット

  • $guradを返す。

  • つまり、前半(Auth::guard()部分)では、SessionGuardクラスのオブジェクト取得が目的


createUserProvider()がやってること


  • configのauth.providers.{$provider}の値 → auth.providers.usersの値を取得する


    • デフォルト:auth.providers.users = ['driver'=>'eloquent','model'=>'App\User']



  • 「何を使って、どこからUser情報を取得するか」というのを取得する。

  • デフォルトでは、「eloquentを使って、App\Userモデルの情報をとる」ということ


new SessionGuard()でやっていること


  • ソースファイル:Illuminate\Auth\SessionGurad.php


SessionGurad.php

    public function __construct($name,

UserProvider $provider,
SessionInterface $session,
Request $request = null)
{
$this->name = $name;
$this->session = $session;
$this->request = $request;
$this->provider = $provider;
}


  • セッションやリクエストのセットを行っている



後半 (Auth::guard($guard)->guest()->guest()部分)


guest()はどこにあるか?


  • Auth::guard()にて、SessionGuardクラスのオブジェクトが返ってきているので、SessionGuardクラスのguest()を見てみる

  • しかし、Illuminate\Auth\SessionGuard.phpにはguest()がない


  • use GuardHelpers;を行い、GuardHelpersクラスをトレイトしている

  • Illuminate\Auth\GuardHelpers.phpにguest()がある


guest()がやっていること


  • ソースファイル:Illuminate\Auth\GuardHelpers.php


  • $this->check()を呼び出し


  • $this->check()は、Illuminate\Auth\SessionGuard.phpの$this->user()を呼び出し


GuardHelpers.php

    public function guest()

{
return ! $this->check();
}


GuardHelpers.php

    public function check()

{
return ! is_null($this->user());
}



  • $this->user()はGuardHelperではなく、SessionGuardにある(戻った…)


  • $this->user()の結果がnullだと、check()はfalse、guest()はtrueを返す


    • guest() == true:ログインしていないということ




SessionGuardのuser()がやっていること


  • ソースファイル:Illuminate\Auth\SessionGuard.php


  • $this->loggedOut変数をチェック。Logoutされていればtrueが設定される


    • ログアウトしてもセッションが残っているとかの予防?



  • $idがsessionに保存されているかチェック

$id = $this->session->get($this->getName());


  • Sessionに$idがあれば、Usersテーブルを検索し、ログイン中ユーザーを返す

if (! is_null($id)) {

$user = $this->provider->retrieveById($id);
}


  • remenber meが有効かチェック


  • $this->getRecaller()でクッキーに保存されているトークンを取得

protected function getRecaller()

{
return $this->request->cookies->get($this->getRecallerName());
}



  • $this->getUserByRecaller()でUsersテーブルを検索


    • トークンは、remenber meを有効にするとログイン時にUsersテーブルに保存される



  • Sesssion、もしくはRecallerで$userがあればログインユーザーを返す


  • ログインユーザーがいない場合、nullが返る(ログインしていないとなる)