View Single Post
  #2 (permalink)  
Old 06-27-2008, 06:01 PM
rabergli rabergli is offline
Junior Member
 
Join Date: Jun 2008
Location: Nevada
Posts: 2
Default A brute-force inactivity timeout

This method is rather brute-force, but it works reasonably well. First, in the bootstrap file, I started a session (this is a best practice anyway):

Code:
<?php
// ...

// Start up a session
require_once 'Zend/Session.php';
Zend_Session::start();

// ...
I created a LoginController.php separate from the other controllers. In that controller, I added this code (using a session namespace to track timeouts, as well as the user's current location):

Code:
<?php
// LoginController.php - Controls application login/logout

class LoginController extends Zend_Controller_Action
{
    // Application login function.  Runs under the URL http://app/Login/login.
    function loginAction()
    {
        // ... do the login stuff ...

        // .. at the point of a successful login ...
        if (Zend_Auth::getInstance()->hasIdentity()) {
            $authNamespace = new Zend_Session_Namespace('auth');
            // timeout is 20 minutes (1200 seconds)
            $authNamespace->timeout = time() + 1200;
            // If possible, redirect to the page we came from (see the
            // preDispatch routine).  Otherwise, go to the main index page.
            if (isset($authNamespace->requestUri)) {
                $this->_redirect($authNamespace->requestUri);
            } else {
                $this->_redirect('/');
            }
        }
    }
    // ...
In all the other controllers, I added a preDispatch() function, which is a hook provided by Zend to perform non-standard functions:

Code:
<?php
// IndexController.php (or any other controller other than LoginController)

class IndexController extends Zend_Controller_Action
{
    function preDispatch()
    {
        $authNamespace = new Zend_Session_Namespace('auth');
        // clear the identity of a user who has not accessed a controller for
        // longer than a timeout period.
        if (isset($authNamespace->timeout) && time() > $authNamespace->timeout) {
            Zend_Auth::getInstance()->clearIdentity();
        } else {
            // User is still active - update the timeout time.
            $authNamespace->timeout = time() + 1200;
            // Store the request URI so that an authentication after a timeout
            // can be directed back to the pre-timeout display.  The base URL needs to
            // be stripped off of the request URI to function properly.
            $authNamespace->requestUri = substr($this->_request->getRequestUri(),
                strlen(Zend_Controller_Front::getInstance()->getBaseUrl()));
        }
        // If the user has no identity here, there has either been a time out or the user has
        // not logged in yet.
        if (!Zend_Auth::getInstance()->hasIdentity()) {
            $this->_redirect('/Login/login');
        }
    }
    // ...
There is one downside to this code: after a timeout re-authentication, control returns back to where the user was at timeout (i.e., it does not follow the current request). To me, this is a fairly minor problem.

This code seems to work fine on these configurations:

Zend Framework v1.5.2 on Linux or OS-X
PHP v5.2.6 on Linux or OS-X
Apache v2.2.9 on Linux or OS-X
Firefox v3.0 on Linux
Konqueror v3.5.7 on Linux
Firefox v2.0.0.14 on OS-X
Safari v3.1.1 on OS-X
Reply With Quote