LoginSignup
1
2

More than 3 years have passed since last update.

laravel session 仕組み

Posted at

Laravel sessionの仕組みを追う

SessionServiceProvider.phpでSessionの仕組みがLaravelで使えるようになる。
ここでは、
1. SessionManagerの登録
2. SessionDriverの登録
3. StartSession::classのDI登録
を行う。

SessionServiceProvider.php
    public function register()
    {
        $this->registerSessionManager();

        $this->registerSessionDriver();

        $this->app->singleton(StartSession::class, function () {
            return new StartSession($this->app->make(SessionManager::class), function () {
                return $this->app->make(CacheFactory::class);
            });
        });
    }

registerSessionManager

sessionをキーにSessionManagerを登録する。

    protected function registerSessionManager()
    {
        $this->app->singleton('session', function ($app) {
            return new SessionManager($app);
        });
    }

registerSessionDriver

session.storeでセッションのドライバーが返るようにする。


    protected function registerSessionDriver()
    {
        $this->app->singleton('session.store', function ($app) {
            // First, we will create the session manager which is responsible for the
            // creation of the various session drivers when they are needed by the
            // application instance, and will resolve them on a lazy load basis.
            return $app->make('session')->driver();
        });
    }

StartSession

StartSessionはミドルウェアでKernel.phpの$middlewareGroupsで指定されている。
StartSessionでセッション処理の起動を行う


    protected $middlewareGroups = [
        'web' => [
            \Illuminate\Session\Middleware\StartSession::class,
            ...
        ],

handle関数では以下を行っている。
1. session設定されているか確認し、設定されていないなら次のミドルウェアに処理を進める
2. sessionドライバーを取得
3. ブロックの有無に合わせてセッション管理


    public function handle($request, Closure $next)
    {
        if (! $this->sessionConfigured()) {
            return $next($request);
        }

        $session = $this->getSession($request);

        if ($this->manager->shouldBlock() ||
            ($request->route() instanceof Route && $request->route()->locksFor())) {
            return $this->handleRequestWhileBlocking($request, $session, $next);
        } else {
            return $this->handleStatefulRequest($request, $session, $next);
        }
    }

getSession

getSessionではsessionIdをセットしたドライバーを返す。
$this->manager->driver()ではSessionManagerインスタンスのdriver関数を実行する。
driver関数ではconfigのsession.phpのdriverで指定したdriverインスタンスを返す。


    public function getSession(Request $request)
    {
        // $session->getName()はconfigのsession.cookieの値。それを元にcookie値を取得する。
        return tap($this->manager->driver(), function ($session) use ($request) {
            $session->setId($request->cookies->get($session->getName()));
        });
    }

driverとしてどのインスタンスが返されるかはSessionManagerをみると分かる。
ドライバー作成時にcreateOOOODriver()関数が実行される。OOOはドライバー名。
SessionManagerには↓のような関数があり、具体的なインスタンスが分かる。


    protected function createFileDriver()
    {
        return $this->createNativeDriver();
    }

createNativeDriverではbuildSession関数で暗号するしないの設定に合わせてstoreインスタンスを返します。
ドライバーごとにhandlerインスタンスを作成し、storeインスタンスに渡す。

    protected function createNativeDriver()
    {
        $lifetime = $this->config->get('session.lifetime');

        return $this->buildSession(new FileSessionHandler(
            $this->container->make('files'), $this->config->get('session.files'), $lifetime
        ));
    }

handleStatefulRequest

handleStatefulRequest関数では以下を行う
1. セッションを開始
2. 一定の確率でゴミ掃除
3. 次のmiddlewareを実行
4. 必要ならsessionに現在のurlを設定
5. cookieにsessionを登録


    protected function handleStatefulRequest(Request $request, $session, Closure $next)
    {
        // If a session driver has been configured, we will need to start the session here
        // so that the data is ready for an application. Note that the Laravel sessions
        // do not make use of PHP "native" sessions in any way since they are crappy.
        $request->setLaravelSession(
            $this->startSession($request, $session)
        );

        $this->collectGarbage($session);

        $response = $next($request);

        $this->storeCurrentUrl($request, $session);

        $this->addCookieToResponse($response, $session);

        // Again, if the session has been configured we will need to close out the session
        // so that the attributes may be persisted to some storage medium. We will also
        // add the session identifier cookie to the application response headers now.
        $this->saveSession($request);

        return $response;
    }

startSession

setRequestOnHandlerで必要な場合はハンドラーにリクエストをセットする。(現状CookieSessionHandlerのみ)
start関数では以下を行う
1. sessionをload
2. _tokenがあればtokenを再作成

    protected function startSession(Request $request, $session)
    {
        return tap($session, function ($session) use ($request) {
            $session->setRequestOnHandler($request);

            $session->start();
        });
    }

    public function start()
    {
        $this->loadSession();

        if (! $this->has('_token')) {
            $this->regenerateToken();
        }

        return $this->started = true;
    }

addCookieToResponse

cookieにsessionIdを登録する


    protected function addCookieToResponse(Response $response, Session $session)
    {
        if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) {
            $response->headers->setCookie(new Cookie(
                $session->getName(), $session->getId(), $this->getCookieExpirationDate(),
                $config['path'], $config['domain'], $config['secure'] ?? false,
                $config['http_only'] ?? true, false, $config['same_site'] ?? null
            ));
        }
    }

試しにLaravelページのcookieをみるとsessionIdが登録されているのが分かる。
スクリーンショット 2021-01-18 1.38.59.png

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2