Stop ACTA

RememberMe component, the final word

Posted in CakePHP on 01.07.2008.

This is really starting to be annoying, but it is also showing how much one can evolve by learning CakePHP in more detail.

I promise, this is the last version of this component. When I first started messing with the "remember me" on a user login, I never thought I'd write this much text on the topic.

Anyway, the previous version was/is working, but thanks to Baz L, I've decided to revisit this component again. And there was much rejoicing.

First of all, this new version is so simple, your head might explode.

Here it is, in all it's simplicity:

class RememberMeComponent extends Object
{
    var $components = array('Auth', 'Cookie');
    var $controller = null;

    /**
     * Cookie retention period.
     *
     * @var string
     */
    var $period = '+2 weeks';
    var $cookieName = 'User';

    function startup(&$controller)
    {
        $this->controller =& $controller;
    }

    function remember($username, $password)
    {
        $cookie = array();
        $cookie[$this->Auth->fields['username']] = $username;
        $cookie[$this->Auth->fields['password']] = $password;

        $this->Cookie->write(
            $this->cookieName,
            $cookie,
            true,
            $this->period
        );
    }

    function check()
    {
        $cookie = $this->Cookie->read($this->cookieName);

        if (!is_array($cookie) || $this->Auth->user())
            return;

        if ($this->Auth->login($cookie))
        {
            $this->Cookie->write(
                $this->cookieName,
                $cookie,
                true,
                $this->period
            );
        }
        else
        {
            $this->delete();
        }
    }

    function delete()
    {
        $this->Cookie->del($this->cookieName);
    }
}

So there. I'm letting Auth worry about the model and the username & password fields. The usage of this component remains the same:

class UsersController extends AppController
{
    var $name = 'Users';
    var $uses = array('User');

    function login()
    {
        if (!$this->Auth->user())
        {
            return;
        }

        if (empty($this->data))
        {
            $this->redirect($this->Auth->redirect());
        }

        if (empty($this->data['User']['remember_me']))
        {
            $this->RememberMe->delete();
        }
        else
        {
            $this->RememberMe->remember
                (
                    $this->data['User']['username'],
                    $this->data['User']['password']
                );
        }

        unset($this->data['User']['remember_me']);
        $this->redirect($this->Auth->redirect());
    }

    function logout()
    {
        $this->RememberMe->delete();
        $this->redirect($this->Auth->logout());
    }
}

And the app controller:

class AppController extends Controller
{
    var $components = array('RememberMe');

    function beforeFilter()
    {
        // again, you can customize the component settings here,
        // like this:
        // $this->RememberMe->period = '+2 months';
        // $this->RememberMe->cookieName = 'Gobshite';

        $this->RememberMe->check();
    }
}   

That's pretty much it. I hope I won't discover a new mega-bull in this code, I don't want to go around the Europe again, hitting myself with a plank and saying things like Pie Jesu Domine, Donna eis requiem...

The component is available for download here:

Happy baking!

Article comments — View · Add


Page 1 of 5
1 · 2 · 3 · 4 · 5

Paul Gardner :: 07.12.2008 15:34:27
I came to this component page from your comment on the http://bakery.cakephp.org/articles/view/remember-me-a-component-to-add-upon-basic-auth bakery article in the hope your solution would work but I am having no joy.

Not sure if I'm being daft but it seems you missed out two things above:

1. Need to add 'RememberMe' component to AppController
2. Add a 'User.remember_me' checkbox to the login form

Despite doing these things the RememberMe->check() function keeps returning at the following point.

if (!is_array($cookie) || $this->Auth->user())
return;

A cookie never gets created ... any ideas?
lecterror :: 08.12.2008 05:35:31
Hi Paul!

I'm sorry to hear you're having trouble. For the rest of the code please refer to my previous articles on the subject, or download NeutrinoCMS (beta) for a live example (I'm using it on this site and can confirm that it works). Hope that will help!

Good luck!
Paul Gardner :: 08.12.2008 09:05:26
Could it be something to do with the fact I am running my site securely? (i.e. on https://)
lecterror :: 09.12.2008 08:41:51
It is possible. I've never used cookies over SSL, but as far as I know, if you write a cookie over SSL it will be readable over SSL only and not by regular HTTP. So basically, check if you're reading and writing over the same protocol :)

Although it is strange that you cookie is never created.. could your browser settings be messed up?

In any case, good luck!
alex :: 03.01.2009 13:32:40
Couple of points:

1. AppController also needs the 'Auth' component, before 'RememberMe'.

2. UserController cannot have a beforeFilter (such as $this->Auth->allow()), as this seems to conflict with the beforeFilter of the AppController. I had to move everything to the beforeFilter of the AppController.