From 9f87aa56ac925ab4269596f207205e5f871c10e7 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 20 Mar 2024 17:40:41 +0100 Subject: [PATCH] Move check for `FORCE_LOGIN` into a Middleware Closes #5853 --- .../files/lib/form/LoginForm.class.php | 20 ++--- .../middleware/CheckForForceLogin.class.php | 79 +++++++++++++++++++ .../files/lib/page/AbstractPage.class.php | 37 +-------- .../system/request/RequestHandler.class.php | 2 + 4 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 wcfsetup/install/files/lib/http/middleware/CheckForForceLogin.class.php diff --git a/wcfsetup/install/files/lib/form/LoginForm.class.php b/wcfsetup/install/files/lib/form/LoginForm.class.php index f18e846e70..cdf0b94802 100644 --- a/wcfsetup/install/files/lib/form/LoginForm.class.php +++ b/wcfsetup/install/files/lib/form/LoginForm.class.php @@ -9,25 +9,19 @@ use wcf\system\WCF; /** * Shows the user login form. * - * @author Marcel Werk - * @copyright 2001-2020 WoltLab GmbH - * @license GNU Lesser General Public License + * @author Marcel Werk + * @copyright 2001-2024 WoltLab GmbH + * @license GNU Lesser General Public License */ class LoginForm extends \wcf\acp\form\LoginForm { const AVAILABLE_DURING_OFFLINE_MODE = true; - /** - * @inheritDoc - */ + #[\Override] public function save() { AbstractForm::save(); - if (FORCE_LOGIN) { - WCF::getSession()->unregister('__wsc_forceLoginRedirect'); - } - // change user $needsMultifactor = WCF::getSession()->changeUserAfterMultifactorAuthentication($this->user); @@ -42,15 +36,13 @@ class LoginForm extends \wcf\acp\form\LoginForm $this->performRedirect($needsMultifactor); } - /** - * @inheritDoc - */ + #[\Override] public function assignVariables() { parent::assignVariables(); WCF::getTPL()->assign([ - 'forceLoginRedirect' => (FORCE_LOGIN && WCF::getSession()->getVar('__wsc_forceLoginRedirect') !== null), + 'forceLoginRedirect' => FORCE_LOGIN, ]); } } diff --git a/wcfsetup/install/files/lib/http/middleware/CheckForForceLogin.class.php b/wcfsetup/install/files/lib/http/middleware/CheckForForceLogin.class.php new file mode 100644 index 0000000000..4bda5c80f5 --- /dev/null +++ b/wcfsetup/install/files/lib/http/middleware/CheckForForceLogin.class.php @@ -0,0 +1,79 @@ + + * @since 6.1 + */ +final class CheckForForceLogin implements MiddlewareInterface +{ + private const ALLOWED_CONTROLLERS = [ + \wcf\form\EmailActivationForm::class, + \wcf\form\EmailNewActivationCodeForm::class, + \wcf\form\LoginForm::class, + \wcf\form\LostPasswordForm::class, + \wcf\form\NewPasswordForm::class, + \wcf\form\RegisterActivationForm::class, + \wcf\form\RegisterForm::class, + \wcf\form\RegisterNewActivationCodeForm::class, + \wcf\page\DisclaimerPage::class, + ]; + + /** + * @inheritDoc + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ( + !$this->forceLoginEnabled() + || RequestHandler::getInstance()->isACPRequest() + || $this->userCanBypassForceLogin() + || $this->requestCanBypassForceLogin() + ) { + return $handler->handle($request); + } + + return new RedirectResponse( + LinkHandler::getInstance()->getControllerLink(LoginForm::class) + ); + } + + private function forceLoginEnabled(): bool + { + return \defined('FORCE_LOGIN') && FORCE_LOGIN; + } + + private function userCanBypassForceLogin(): bool + { + return WCF::getUser()->userID ? true : false; + } + + private function requestCanBypassForceLogin(): bool + { + $controller = RequestHandler::getInstance()->getActiveRequest()->getClassName(); + if (\in_array($controller, self::ALLOWED_CONTROLLERS, true)) { + return true; + } + + if (RequestHandler::getInstance()->getActiveRequest()->isAvailableDuringOfflineMode()) { + return true; + } + + return false; + } +} diff --git a/wcfsetup/install/files/lib/page/AbstractPage.class.php b/wcfsetup/install/files/lib/page/AbstractPage.class.php index 306c4caf90..95de89ec85 100644 --- a/wcfsetup/install/files/lib/page/AbstractPage.class.php +++ b/wcfsetup/install/files/lib/page/AbstractPage.class.php @@ -253,10 +253,6 @@ abstract class AbstractPage implements IPage */ public function show() { - if (FORCE_LOGIN && !RequestHandler::getInstance()->isACPRequest() && !WCF::getUser()->userID) { - $this->forceLogin(); - } - // check if active user is logged in if ($this->loginRequired && !WCF::getUser()->userID) { throw new PermissionDeniedException(); @@ -400,41 +396,10 @@ abstract class AbstractPage implements IPage } /** - * Forces visitors to log-in themselves to access the site. + * @deprecated 6.1 handled by the `CheckForForceLogin` middleware */ protected function forceLogin() { - $allowedControllers = [ - DisclaimerPage::class, - EmailActivationForm::class, - EmailNewActivationCodeForm::class, - LoginForm::class, - LostPasswordForm::class, - MediaPage::class, - NewPasswordForm::class, - RegisterActivationForm::class, - RegisterForm::class, - RegisterNewActivationCodeForm::class, - ]; - if (\in_array(static::class, $allowedControllers)) { - // controller is allowed - return; - } - - if (WCF::getActiveRequest()->isAvailableDuringOfflineMode()) { - // allow access to those pages that should be always available - return; - } - - // force redirect to login form - WCF::getSession()->register('__wsc_forceLoginRedirect', true); - HeaderUtil::redirect( - LinkHandler::getInstance()->getLink('Login', [ - 'url' => WCF::getRequestURI(), - ]) - ); - - exit; } /** diff --git a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php index 6d22233507..ddd21490b1 100644 --- a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php @@ -16,6 +16,7 @@ use wcf\http\LegacyPlaceholderResponse; use wcf\http\middleware\AddAcpSecurityHeaders; use wcf\http\middleware\CheckForEnterpriseNonOwnerAccess; use wcf\http\middleware\CheckForExpiredAppEvaluation; +use wcf\http\middleware\CheckForForceLogin; use wcf\http\middleware\CheckForMultifactorRequirement; use wcf\http\middleware\CheckForOfflineMode; use wcf\http\middleware\CheckHttpMethod; @@ -144,6 +145,7 @@ final class RequestHandler extends SingletonFactory new CheckForEnterpriseNonOwnerAccess(), new CheckForExpiredAppEvaluation(), new CheckForOfflineMode(), + new CheckForForceLogin(), new CheckForMultifactorRequirement(), new JsonBody(), new TriggerBackgroundQueue(), -- 2.20.1