123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <?php
-
- namespace Illuminate\Session\Middleware;
-
- use Closure;
- use Illuminate\Http\Request;
- use Illuminate\Support\Carbon;
- use Illuminate\Session\SessionManager;
- use Illuminate\Contracts\Session\Session;
- use Illuminate\Session\CookieSessionHandler;
- use Symfony\Component\HttpFoundation\Cookie;
- use Symfony\Component\HttpFoundation\Response;
-
- class StartSession
- {
- /**
- * The session manager.
- *
- * @var \Illuminate\Session\SessionManager
- */
- protected $manager;
-
- /**
- * Indicates if the session was handled for the current request.
- *
- * @var bool
- */
- protected $sessionHandled = false;
-
- /**
- * Create a new session middleware.
- *
- * @param \Illuminate\Session\SessionManager $manager
- * @return void
- */
- public function __construct(SessionManager $manager)
- {
- $this->manager = $manager;
- }
-
- /**
- * Handle an incoming request.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Closure $next
- * @return mixed
- */
- public function handle($request, Closure $next)
- {
- $this->sessionHandled = true;
-
- // 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.
- if ($this->sessionConfigured()) {
- $request->setLaravelSession(
- $session = $this->startSession($request)
- );
-
- $this->collectGarbage($session);
- }
-
- $response = $next($request);
-
- // 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.
- if ($this->sessionConfigured()) {
- $this->storeCurrentUrl($request, $session);
-
- $this->addCookieToResponse($response, $session);
- }
-
- return $response;
- }
-
- /**
- * Perform any final actions for the request lifecycle.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Symfony\Component\HttpFoundation\Response $response
- * @return void
- */
- public function terminate($request, $response)
- {
- if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions()) {
- $this->manager->driver()->save();
- }
- }
-
- /**
- * Start the session for the given request.
- *
- * @param \Illuminate\Http\Request $request
- * @return \Illuminate\Contracts\Session\Session
- */
- protected function startSession(Request $request)
- {
- return tap($this->getSession($request), function ($session) use ($request) {
- $session->setRequestOnHandler($request);
-
- $session->start();
- });
- }
-
- /**
- * Get the session implementation from the manager.
- *
- * @param \Illuminate\Http\Request $request
- * @return \Illuminate\Contracts\Session\Session
- */
- public function getSession(Request $request)
- {
- return tap($this->manager->driver(), function ($session) use ($request) {
- $session->setId($request->cookies->get($session->getName()));
- });
- }
-
- /**
- * Remove the garbage from the session if necessary.
- *
- * @param \Illuminate\Contracts\Session\Session $session
- * @return void
- */
- protected function collectGarbage(Session $session)
- {
- $config = $this->manager->getSessionConfig();
-
- // Here we will see if this request hits the garbage collection lottery by hitting
- // the odds needed to perform garbage collection on any given request. If we do
- // hit it, we'll call this handler to let it delete all the expired sessions.
- if ($this->configHitsLottery($config)) {
- $session->getHandler()->gc($this->getSessionLifetimeInSeconds());
- }
- }
-
- /**
- * Determine if the configuration odds hit the lottery.
- *
- * @param array $config
- * @return bool
- */
- protected function configHitsLottery(array $config)
- {
- return random_int(1, $config['lottery'][1]) <= $config['lottery'][0];
- }
-
- /**
- * Store the current URL for the request if necessary.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Illuminate\Contracts\Session\Session $session
- * @return void
- */
- protected function storeCurrentUrl(Request $request, $session)
- {
- if ($request->method() === 'GET' && $request->route() && ! $request->ajax()) {
- $session->setPreviousUrl($request->fullUrl());
- }
- }
-
- /**
- * Add the session cookie to the application response.
- *
- * @param \Symfony\Component\HttpFoundation\Response $response
- * @param \Illuminate\Contracts\Session\Session $session
- * @return void
- */
- protected function addCookieToResponse(Response $response, Session $session)
- {
- if ($this->usingCookieSessions()) {
- $this->manager->driver()->save();
- }
-
- 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
- ));
- }
- }
-
- /**
- * Get the session lifetime in seconds.
- *
- * @return int
- */
- protected function getSessionLifetimeInSeconds()
- {
- return ($this->manager->getSessionConfig()['lifetime'] ?? null) * 60;
- }
-
- /**
- * Get the cookie lifetime in seconds.
- *
- * @return \DateTimeInterface
- */
- protected function getCookieExpirationDate()
- {
- $config = $this->manager->getSessionConfig();
-
- return $config['expire_on_close'] ? 0 : Carbon::now()->addMinutes($config['lifetime']);
- }
-
- /**
- * Determine if a session driver has been configured.
- *
- * @return bool
- */
- protected function sessionConfigured()
- {
- return ! is_null($this->manager->getSessionConfig()['driver'] ?? null);
- }
-
- /**
- * Determine if the configured session driver is persistent.
- *
- * @param array|null $config
- * @return bool
- */
- protected function sessionIsPersistent(array $config = null)
- {
- $config = $config ?: $this->manager->getSessionConfig();
-
- return ! in_array($config['driver'], [null, 'array']);
- }
-
- /**
- * Determine if the session is using cookie sessions.
- *
- * @return bool
- */
- protected function usingCookieSessions()
- {
- if ($this->sessionConfigured()) {
- return $this->manager->driver()->getHandler() instanceof CookieSessionHandler;
- }
-
- return false;
- }
- }
|