Browse Source

Allow running initial auth checks earlier.

If 'earlyAuth' config is set to true initial auth checks are done
in beforeFilter() allback instead of startup(), thus making user
info available in controller's beforeFilter().
ADmad 10 years ago
parent
commit
dce5db0214

+ 35 - 4
src/Controller/Component/AuthComponent.php

@@ -138,6 +138,10 @@ class AuthComponent extends Component
      * - `storage` - Storage class to use for persisting user record. When using
      *   stateless authenticator you should set this to 'Memory'. Defaults to 'Session'.
      *
+     * - 'earlyAuth' - If set to true initial auth checks are done in beforeFilter()
+     *   callback instead of startup(), i.e. before controller's beforeFilter().
+     *   Defaults to false for backwards compatibility.
+     *
      * @var array
      */
     protected $_defaultConfig = [
@@ -150,7 +154,8 @@ class AuthComponent extends Component
         'logoutRedirect' => null,
         'authError' => null,
         'unauthorizedRedirect' => true,
-        'storage' => 'Session'
+        'storage' => 'Session',
+        'earlyAuth' => false
     ];
 
     /**
@@ -243,14 +248,40 @@ class AuthComponent extends Component
     }
 
     /**
-     * Main execution method. Handles redirecting of invalid users, and processing
-     * of login form data.
+     * Callback for Controller.initialize event.
+     *
+     * @param \Cake\Event\Event $event The Controller.initialize event instance.
+     * @return void|\Cake\Network\Response
+     */
+    public function beforeFilter(Event $event)
+    {
+        if ($this->_config['earlyAuth']) {
+            return $this->_authCheck($event);
+        }
+    }
+
+    /**
+     * Callback for Controller.startup event.
      *
-     * @param \Cake\Event\Event $event The startup event.
+     * @param \Cake\Event\Event $event The Controller.startup event instance.
      * @return void|\Cake\Network\Response
      */
     public function startup(Event $event)
     {
+        if (!$this->_config['earlyAuth']) {
+            return $this->_authCheck($event);
+        }
+    }
+
+    /**
+     * Main execution method. Handles initial authentication check and redirecting
+     * of invalid users.
+     *
+     * @param \Cake\Event\Event $event Event instance.
+     * @return void|\Cake\Network\Response
+     */
+    public function _authCheck(Event $event)
+    {
         $controller = $event->subject();
 
         $action = strtolower($controller->request->params['action']);

+ 20 - 0
tests/TestCase/Controller/Component/AuthComponentTest.php

@@ -1396,4 +1396,24 @@ class AuthComponentTest extends TestCase
         $this->Auth->sessionKey = false;
         $this->assertInstanceOf('Cake\Auth\Storage\MemoryStorage', $this->Auth->storage());
     }
+
+    /**
+     * Test that setting config 'earlyAuth' to true make AuthComponent do the initial
+     * checks in beforeFilter() instead of startup().
+     *
+     * @return void
+     */
+    public function testEarlyAuthConfig()
+    {
+        $this->Controller->components()->set('Auth', $this->Auth);
+        $this->Auth->earlyAuthTest = true;
+
+        $this->Controller->startupProcess();
+        $this->assertEquals('Controller.startup', $this->Auth->authCheckCalledFrom);
+
+        $this->Auth->authCheckCalledFrom = null;
+        $this->Auth->config('earlyAuth', true);
+        $this->Controller->startupProcess();
+        $this->assertEquals('Controller.initialize', $this->Auth->authCheckCalledFrom);
+    }
 }

+ 10 - 0
tests/test_app/TestApp/Controller/Component/TestAuthComponent.php

@@ -14,6 +14,7 @@
 namespace TestApp\Controller\Component;
 
 use Cake\Controller\Component\AuthComponent;
+use Cake\Event\Event;
 
 /**
  * TestAuthComponent class
@@ -21,6 +22,15 @@ use Cake\Controller\Component\AuthComponent;
  */
 class TestAuthComponent extends AuthComponent
 {
+    public function _authCheck(Event $event)
+    {
+        if (isset($this->earlyAuthTest)) {
+            $this->authCheckCalledFrom = $event->name;
+            return;
+        }
+
+        return parent::_authCheck($event);
+    }
 
     /**
      * Helper method to add/set an authenticate object instance