From 3363b219f6d0613abdfcf9defaa962919f61ee2f Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Thu, 21 Mar 2019 15:19:28 +0800 Subject: [PATCH] Delay backend controller middleware until after request is processed (#4190) Credit to @bennothommo. Fixes #4183. --- modules/backend/classes/BackendController.php | 65 +++++++++++++------ modules/backend/controllers/Auth.php | 10 +-- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/modules/backend/classes/BackendController.php b/modules/backend/classes/BackendController.php index 1cac77354..7ccbfdd55 100644 --- a/modules/backend/classes/BackendController.php +++ b/modules/backend/classes/BackendController.php @@ -50,32 +50,51 @@ class BackendController extends ControllerBase */ protected $cmsHandling = false; + /** + * Stores the requested controller so that the constructor is only run once + * + * @var Backend\Classes\Controller + */ + protected $requestedController; + /** * Instantiate a new BackendController instance. */ public function __construct() { - // Find requested controller to determine if any middleware has been attached - $pathParts = explode('/', str_replace(Request::root() . '/', '', Request::url())); - if (count($pathParts)) { - // Drop off preceding backend URL part if needed - if (!empty(Config::get('cms.backendUri', 'backend'))) { - array_shift($pathParts); - } - $path = implode('/', $pathParts); + $this->middleware(function ($request, $next) { + // Process the request before retrieving controller middleware, to allow for the session and auth data + // to be made available to the controller's constructor. + $response = $next($request); - $requestedController = $this->getRequestedController($path); - if (!is_null($requestedController) && count($requestedController['controller']->getMiddleware())) { - $action = $requestedController['action']; + // Find requested controller to determine if any middleware has been attached + $pathParts = explode('/', str_replace(Request::root() . '/', '', Request::url())); + if (count($pathParts)) { + // Drop off preceding backend URL part if needed + if (!empty(Config::get('cms.backendUri', 'backend'))) { + array_shift($pathParts); + } + $path = implode('/', $pathParts); - // Collect applicable middleware and insert middleware into pipeline - collect($requestedController['controller']->getMiddleware())->reject(function ($data) use ($action) { - return static::methodExcludedByOptions($action, $data['options']); - })->pluck('middleware')->map(function ($middleware) { - $this->middleware($middleware); - }); + $requestedController = $this->getRequestedController($path); + if (!is_null($requestedController) && count($requestedController['controller']->getMiddleware())) { + $action = $requestedController['action']; + + // Collect applicable middleware and insert middleware into pipeline + $controllerMiddleware = collect($requestedController['controller']->getMiddleware()) + ->reject(function ($data) use ($action) { + return static::methodExcludedByOptions($action, $data['options']); + }) + ->pluck('middleware'); + + foreach ($controllerMiddleware as $middleware) { + $middleware->call($requestedController['controller'], $request, $response); + } + } } - } + + return $response; + }); $this->extendableConstruct(); } @@ -224,6 +243,10 @@ class BackendController extends ControllerBase */ protected function findController($controller, $action, $inPath) { + if (isset($this->requestedController)) { + return $this->requestedController; + } + /* * Workaround: Composer does not support case insensitivity. */ @@ -236,16 +259,16 @@ class BackendController extends ControllerBase } if (!class_exists($controller)) { - return false; + return $this->requestedController = null; } $controllerObj = App::make($controller); if ($controllerObj->actionExists($action)) { - return $controllerObj; + return $this->requestedController = $controllerObj; } - return false; + return $this->requestedController = null; } /** diff --git a/modules/backend/controllers/Auth.php b/modules/backend/controllers/Auth.php index b8a38a0af..2d4956cd3 100644 --- a/modules/backend/controllers/Auth.php +++ b/modules/backend/controllers/Auth.php @@ -33,20 +33,16 @@ class Auth extends Controller { parent::__construct(); - $this->middleware(function ($request, $next) { - $response = $next($request); + $this->middleware(function ($request, $response) { // Clear Cache and any previous data to fix Invalid security token issue, see github: #3707 $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); - return $response; })->only('signin'); // Only run on HTTPS connections if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on") { - $this->middleware(function ($request, $next) { - $response = $next($request); + $this->middleware(function ($request, $response) { // Add HTTP Header 'Clear Site Data' to remove all Sensitive Data when signout, see github issue: #3707 $response->headers->set('Clear-Site-Data', 'cache, cookies, storage, executionContexts'); - return $response; })->only('signout'); } @@ -232,4 +228,4 @@ class Auth extends Controller return Backend::redirect('backend/auth/signin'); } -} \ No newline at end of file +}