diff --git a/src/AutoLoginMiddleware.php b/src/AutoLoginMiddleware.php new file mode 100644 index 0000000..1b63150 --- /dev/null +++ b/src/AutoLoginMiddleware.php @@ -0,0 +1,93 @@ +sessionManager = $sessionManager; + $this->options = $options; + $this->authenticationService = $authenticationService; + $this->adapter = $adapter; + $this->userTokenService = $userTokenService; + } + + /** + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $config = $this->sessionManager->getConfig(); + if ($config->getUseCookies() && ! $this->authenticationService->hasIdentity()) { + $key = $this->options->getCookieName(); + $rememberMe = $request->getCookieParams()[$key] ?? null; + if (is_null($rememberMe)) { + return $handler->handle($request); + } + /** @var UserToken $token */ + $token = $this->userTokenService->findOneBy(['value' => base64_decode($rememberMe)]); + if ($token instanceof UserToken && ! $token->isTokenExpired()) { + $this->authenticationService->setAdapter($this->adapter); + $this->adapter->setIdentity($token->getUser()->getIdentity()); + $authResult = $this->authenticationService->authenticate(); + if ($authResult->isValid()) { + $identity = $authResult->getIdentity(); + $this->authenticationService->getStorage()->write($identity); + } else { + $this->userTokenService->destroyToken($token); + } + } + } + return $handler->handle($request); + } +} \ No newline at end of file diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 1f5ed77..3f5b612 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -9,6 +9,7 @@ namespace Dot\Session; +use Dot\Session\Factory\AutoLoginMiddlewareFactory; use Dot\Session\Factory\ContainerAbstractServiceFactory; use Dot\Session\Factory\SessionMiddlewareFactory; use Dot\Session\Factory\SessionOptionsFactory; @@ -35,21 +36,7 @@ public function __invoke(): array { return [ 'dependencies' => $this->getDependencyConfig(), - - 'dot_session' => [ - 'remember_me_inactive' => 1800, - ], - - 'session_config' => [ - 'name' => 'DOT_SESSID', - 'use_cookies' => true, - 'cookie_secure' => false, - 'cookie_httponly' => true, - 'remember_me_seconds' => 1800, - 'cookie_lifetime' => 1800, - 'gc_maxlifetime' => 1800, - ], - + 'session_manager' => [ 'validators' => [], 'options' => [], @@ -80,6 +67,7 @@ public function getDependencyConfig(): array SessionOptions::class => SessionOptionsFactory::class, SessionMiddleware::class => SessionMiddlewareFactory::class, + AutoLoginMiddleware::class => AutoLoginMiddlewareFactory::class, ], 'abstract_factories' => [ ContainerAbstractServiceFactory::class, diff --git a/src/Factory/AutoLoginMiddlewareFactory.php b/src/Factory/AutoLoginMiddlewareFactory.php new file mode 100644 index 0000000..2389257 --- /dev/null +++ b/src/Factory/AutoLoginMiddlewareFactory.php @@ -0,0 +1,34 @@ +get(SessionManager::class), + $container->get(SessionOptions::class), + $container->get(AuthenticationService::class), + $container->get(PersistentAuthenticationAdapter::class), + $container->get(UserTokenService::class), + ); + } +} \ No newline at end of file diff --git a/src/Factory/SessionMiddlewareFactory.php b/src/Factory/SessionMiddlewareFactory.php index 3ed1106..efade25 100644 --- a/src/Factory/SessionMiddlewareFactory.php +++ b/src/Factory/SessionMiddlewareFactory.php @@ -9,11 +9,16 @@ namespace Dot\Session\Factory; +use Doctrine\ORM\EntityManager; +use Dot\Session\Exception\RuntimeException; use Dot\Session\Options\SessionOptions; use Dot\Session\SessionMiddleware; +use Laminas\Authentication\AuthenticationService; use Psr\Container\ContainerInterface; use Laminas\Session\Container; use Laminas\Session\ManagerInterface; +use Laminas\Log\Logger; + /** * Class SessionMiddlewareFactory @@ -32,8 +37,9 @@ public function __invoke(ContainerInterface $container) : Container::getDefaultManager(); $options = $container->get(SessionOptions::class); - - $middleware = new SessionMiddleware($sessionManager, $options); - return $middleware; + return new SessionMiddleware( + $sessionManager, + $options + ); } } diff --git a/src/Options/SessionOptions.php b/src/Options/SessionOptions.php index c81a009..c3374a5 100644 --- a/src/Options/SessionOptions.php +++ b/src/Options/SessionOptions.php @@ -17,9 +17,15 @@ */ class SessionOptions extends AbstractOptions { + + const COOKIE_DEFAULT_NAME = 'remember_me_token'; + /** @var int */ protected $rememberMeInactive = 1800; + /** @var string $cookieName */ + protected $cookieName = 1800; + /** * @return int */ @@ -35,4 +41,14 @@ public function setRememberMeInactive(int $rememberMeInactive) { $this->rememberMeInactive = $rememberMeInactive; } + + public function getCookieName(): string + { + return $this->cookieName; + } + + public function setCookieName(string $name = self::COOKIE_DEFAULT_NAME) + { + $this->cookieName = $name; + } } diff --git a/src/SessionMiddleware.php b/src/SessionMiddleware.php index 6b25fa8..411b2d7 100644 --- a/src/SessionMiddleware.php +++ b/src/SessionMiddleware.php @@ -9,7 +9,15 @@ namespace Dot\Session; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\Entity; use Dot\Session\Options\SessionOptions; +use Frontend\User\Entity\User; +use Frontend\User\Entity\UserToken; +use Frontend\User\Repository\UserRepository; +use Frontend\User\Repository\UserTokenRepository; +use Laminas\Authentication\AuthenticationServiceInterface; +use Laminas\Log\Logger; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -17,6 +25,7 @@ use Laminas\Session\Config\SessionConfig; use Laminas\Session\Container; use Laminas\Session\SessionManager; +use Exception; /** * Class SessionMiddleware @@ -24,6 +33,8 @@ */ class SessionMiddleware implements MiddlewareInterface { + const REMEMBER_ME_YES = "1"; + /** @var SessionManager */ protected $defaultSessionManager; @@ -35,7 +46,10 @@ class SessionMiddleware implements MiddlewareInterface * @param SessionManager $sessionManager * @param SessionOptions $options */ - public function __construct(SessionManager $sessionManager, SessionOptions $options) + public function __construct( + SessionManager $sessionManager, + SessionOptions $options + ) { $this->defaultSessionManager = $sessionManager; $this->options = $options; @@ -49,26 +63,14 @@ public function __construct(SessionManager $sessionManager, SessionOptions $opti */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - /** @var SessionConfig $config */ - $config = $this->defaultSessionManager->getConfig(); + $now = time(); if (isset($_SESSION['LAST_ACTIVITY']) - && time() - $_SESSION['LAST_ACTIVITY'] > $this->options->getRememberMeInactive() + && $now - $_SESSION['LAST_ACTIVITY'] > $this->options->getRememberMeInactive() ) { $this->defaultSessionManager->destroy(['send_expire_cookie' => true, 'clear_storage' => true]); $this->defaultSessionManager->start(); } - $_SESSION['LAST_ACTIVITY'] = time(); - if ($config->getUseCookies()) { - setcookie( - $config->getName(), - $this->defaultSessionManager->getId(), - time() + $config->getCookieLifetime(), - $config->getCookiePath(), - $config->getCookieDomain(), - (bool) $config->getCookieSecure(), - (bool) $config->getCookieHttpOnly() - ); - } + $_SESSION['LAST_ACTIVITY'] = $now; return $handler->handle($request); } }