views:

1032

answers:

1

I'm trying to implement a login system that will be smart enough to redirect a user back to the page they were on before they decided (or were forced to) go to the login page.

I know this seems like a similar question to this one, and this one, but they do not address both of my scenarios.

There are two scenarios here:

  1. User specifically decides to go to login page:

    <a href="<?php echo $this->url(array(
        'controller'=>'auth',
        'action'=>'login'), 'default', true); ?>">Log In</a>
    
  2. User is redirected because they tried to access protected content:

    if (!Zend_Auth::getInstance()->hasIdentity()) {
        $this->_helper->redirector('login', 'auth');
    }
    

How can I implement a solution for this without displaying the "redirect to" url in the address bar?

+1  A: 

Save the destination URL in the session. I guess you have some kind of access pre-dispatch plug-in. Do it there. And then, in the login form handler, check for the destination URL in the session, and redirect to it after a successful authentication.

Sample code from my project:

class Your_Application_Plugin_Access extends Zend_Controller_Plugin_Abstract {
    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        foreach (self::current_roles() as $role) {
            if (
                Zend_Registry::get('bootstrap')->siteacl->is_allowed(
                    $role,
                    new Site_Action_UriPath($request->getPathInfo())
                )
            ) return; // Allowed
        }

        $this->not_allowed($request);
    }

    private function not_allowed(Zend_Controller_Request_Abstract $request) {
        $destination_url = $request->getPathInfo();

        // If the user is authenticted, but the page is denied for his role, show 403
        // else,
        // save $destination_url to session
        // redirect to login page, with $destination_url saved:
        $request
            ->setPathInfo('/login')
            ->setModuleName('default')
            ->setControllerName('login')
            ->setActionName('index')
            ->setDispatched(false);
    }

    ...

}

Here, current_roles() always contains 'guest', which is unauthenticated user, for which Zend_Auth::hasIdentity() is false.

Ivan Krechetov
No, you'll have to add the controller plugin, like in the sample code I've just added. Also, register this plugin in your application.ini: resources.frontController.plugins.access = "Your_Application_Plugin_Access"
Ivan Krechetov
Would you mind cleaning up the plugin code a little bit? I'm seeing a bunch of stuff that seems specific to your project, but unnecessary for mine. Also, I don't see where you are setting the original url in the session. Am I not seeing it? Or is that part left out?
Andrew
I left saving to session out, yes. Do it at (// save $destination_url to session). You may use for that Zend_Session, or $_SESSION super-global directly. Andrew, how the code looks like exactly depends a lot on how you do things in your application. I believe, at this point it's simple enough to figure the details out.
Ivan Krechetov