mirror of
https://github.com/flarum/core.git
synced 2025-07-30 05:00:56 +02:00
Use Illuminate Session component instead of Symfony
Symfony's component relies on PHP's native session functionality, which is not ideal. It automatically sets its own cookie headers, resulting in this issue: https://github.com/flarum/core/issues/1084#issuecomment-364569953 The Illuminate component is more powerful and has a simpler API for extension with other drivers and such, and fits in nicely with other components we use (the majority of which are from Illuminate).
This commit is contained in:
committed by
Franz Liedke
parent
b4e093ab8a
commit
5672819549
@@ -13,10 +13,10 @@ namespace Flarum\Http\Middleware;
|
||||
|
||||
use Flarum\User\Guest;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
class AuthenticateWithSession implements MiddlewareInterface
|
||||
{
|
||||
@@ -33,7 +33,7 @@ class AuthenticateWithSession implements MiddlewareInterface
|
||||
return $delegate->process($request);
|
||||
}
|
||||
|
||||
private function getActor(SessionInterface $session)
|
||||
private function getActor(Session $session)
|
||||
{
|
||||
$actor = User::find($session->get('user_id')) ?: new Guest;
|
||||
|
||||
|
@@ -12,15 +12,29 @@
|
||||
namespace Flarum\Http\Middleware;
|
||||
|
||||
use Flarum\Http\AccessToken;
|
||||
use Flarum\Http\CookieFactory;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class RememberFromCookie implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* @var CookieFactory
|
||||
*/
|
||||
protected $cookie;
|
||||
|
||||
/**
|
||||
* @param CookieFactory $cookie
|
||||
*/
|
||||
public function __construct(CookieFactory $cookie)
|
||||
{
|
||||
$this->cookie = $cookie;
|
||||
}
|
||||
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$id = array_get($request->getCookieParams(), 'flarum_remember');
|
||||
$id = array_get($request->getCookieParams(), $this->cookie->getName('remember'));
|
||||
|
||||
if ($id) {
|
||||
$token = AccessToken::find($id);
|
||||
@@ -28,8 +42,9 @@ class RememberFromCookie implements MiddlewareInterface
|
||||
if ($token) {
|
||||
$token->touch();
|
||||
|
||||
/** @var \Illuminate\Contracts\Session\Session $session */
|
||||
$session = $request->getAttribute('session');
|
||||
$session->set('user_id', $token->user_id);
|
||||
$session->put('user_id', $token->user_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -13,17 +13,19 @@ namespace Flarum\Http\Middleware;
|
||||
|
||||
use Dflydev\FigCookies\FigResponseCookies;
|
||||
use Flarum\Http\CookieFactory;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Illuminate\Session\SessionManager;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
class StartSession implements MiddlewareInterface
|
||||
{
|
||||
const COOKIE_NAME = 'session';
|
||||
/**
|
||||
* @var SessionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* @var CookieFactory
|
||||
@@ -31,54 +33,75 @@ class StartSession implements MiddlewareInterface
|
||||
protected $cookie;
|
||||
|
||||
/**
|
||||
* @param SessionManager $manager
|
||||
* @param CookieFactory $cookie
|
||||
*/
|
||||
public function __construct(CookieFactory $cookie)
|
||||
public function __construct(SessionManager $manager, CookieFactory $cookie)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
$this->cookie = $cookie;
|
||||
}
|
||||
|
||||
public function process(Request $request, DelegateInterface $delegate)
|
||||
{
|
||||
$session = $this->startSession();
|
||||
$request = $request->withAttribute('session',
|
||||
$session = $this->startSession($request)
|
||||
);
|
||||
|
||||
$request = $request->withAttribute('session', $session);
|
||||
$this->collectGarbage($session);
|
||||
|
||||
$response = $delegate->process($request);
|
||||
|
||||
$session->save();
|
||||
|
||||
$response = $this->withCsrfTokenHeader($response, $session);
|
||||
|
||||
return $this->withSessionCookie($response, $session);
|
||||
}
|
||||
|
||||
private function startSession()
|
||||
private function startSession(Request $request)
|
||||
{
|
||||
$session = new Session;
|
||||
$session = $this->manager->driver();
|
||||
|
||||
$session->setName($this->cookie->getName(self::COOKIE_NAME));
|
||||
$id = array_get($request->getCookieParams(), $this->cookie->getName($session->getName()));
|
||||
|
||||
$session->setId($id);
|
||||
$session->start();
|
||||
|
||||
if (! $session->has('csrf_token')) {
|
||||
$session->set('csrf_token', Str::random(40));
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
private function withCsrfTokenHeader(Response $response, SessionInterface $session)
|
||||
private function collectGarbage(Session $session)
|
||||
{
|
||||
if ($session->has('csrf_token')) {
|
||||
$response = $response->withHeader('X-CSRF-Token', $session->get('csrf_token'));
|
||||
$config = $this->manager->getSessionConfig();
|
||||
|
||||
if ($this->configHitsLottery($config)) {
|
||||
$session->getHandler()->gc($this->getSessionLifetimeInSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
private function configHitsLottery(array $config)
|
||||
{
|
||||
return random_int(1, $config['lottery'][1]) <= $config['lottery'][0];
|
||||
}
|
||||
|
||||
private function withCsrfTokenHeader(Response $response, Session $session)
|
||||
{
|
||||
$response = $response->withHeader('X-CSRF-Token', $session->token());
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function withSessionCookie(Response $response, SessionInterface $session)
|
||||
private function withSessionCookie(Response $response, Session $session)
|
||||
{
|
||||
return FigResponseCookies::set(
|
||||
$response,
|
||||
$this->cookie->make(self::COOKIE_NAME, $session->getId())
|
||||
$this->cookie->make($session->getName(), $session->getId(), $this->getSessionLifetimeInSeconds())
|
||||
);
|
||||
}
|
||||
|
||||
private function getSessionLifetimeInSeconds()
|
||||
{
|
||||
return ($this->manager->getSessionConfig()['lifetime'] ?? null) * 60;
|
||||
}
|
||||
}
|
||||
|
@@ -11,25 +11,26 @@
|
||||
|
||||
namespace Flarum\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
|
||||
class SessionAuthenticator
|
||||
{
|
||||
/**
|
||||
* @param SessionInterface $session
|
||||
* @param Session $session
|
||||
* @param int $userId
|
||||
*/
|
||||
public function logIn(SessionInterface $session, $userId)
|
||||
public function logIn(Session $session, $userId)
|
||||
{
|
||||
$session->migrate();
|
||||
$session->set('user_id', $userId);
|
||||
$session->regenerate(true);
|
||||
$session->put('user_id', $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SessionInterface $session
|
||||
* @param Session $session
|
||||
*/
|
||||
public function logOut(SessionInterface $session)
|
||||
public function logOut(Session $session)
|
||||
{
|
||||
$session->invalidate();
|
||||
$session->regenerateToken();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user