Let’s eat cake and cookies

Published on and tagged with cakephp  component  cookie  testing

One of the new components coming with CakePHP 1.2 is the cookie component. It is a rather simple component, so it is very easy to use this component. Let us do an example.

As always when using a component we have to add the cookie component to the $components array of our controller:

var $components = array('Cookie');

If we now call our controller in the browser we will see the following notices (if we are in the debug modus):

Notice: For added security you should add the var cookieName to your Controller or AppController in 
/home/dho/projects/cake_1.2.x.x/cake/libs/controller/components/cookie.php on line 153
 
Notice: For added security you should add the var cookieKey to your Controller or AppController in 
/home/dho/projects/cake_1.2.x.x/cake/libs/controller/components/cookie.php on line 161
 
Notice: Add var cookieDomain = .yourdomain.com; to your Controller or AppController to allow access on all subdomains in 
/home/dho/projects/cake_1.2.x.x/cake/libs/controller/components/cookie.php on line 169

To remove these notices we do what is recommended in the notices and add the expected variables to our controller:

var $cookieName = 'myCookie';
var $cookieKey = 'has82js737hak2';
var $cookieDomain = '.myproject.localhost';

As it is not very cool to add a development domain to the code, we will refactor a bit and set the domain dynamically in the constructor:

var $cookieDomain;

function __construct() {
    parent::__construct();
    $this->cookieDomain = '.'.$_SERVER['SERVER_NAME'];
}

Writing to the cookie and reading from it is as you would expect:

$this->Cookie->write('User.id', 1);

respectively

$this->Cookie->read('User.id');

For more details see the API (thanks to Christian Winther aka Jippi for providing these API docs).

P.S.: For those of you who are using my unofficial test suite there is a new version available which supports the cookie component. You can use it in your tests as shown in the following test function which tests that a user with a cookie is automatically logged in when requesting /users/login:

function testLoginWithCookie() {
    $this->get('/users/login', null, array('User.id' => $this->dho['id']));
    $this->assertRedirectedTo('/projects');
}

You can also check if the correct value has been written to the cookie with something like:

$this->assertEqual($this->dho['id'], $this->cookie['User.id']);

27 comments baked

  • KesheR

    Thxxxxx

  • speedyop

    the cookie component is in the nightly not the 1.2 release for christmas (1.2.0.4206)

  • Fred

    Actually, I don’t think it’s a good idea to store User IDs in a cookie. Always bear in mind that cookies are forgable, so if you actually used the code up there (I know you just made this up as an example, but…), you might end up inviting evildoers to play with other people’s user accounts.

  • Dieter@be

    I think there is nothing wrong with storing user id’s in cookies per se. If you want to keep evildoers from doing naughty things, you need a good authentication system, along with some decent access control. This does not necessarily mean not putting user id’s in a cookie.
    (not that i see much use in putting user id’s in a cookie, but that’s unrelated, besides as you said it’s probably just an example :-)

  • speedyop

    the cookie component encrypt the string of the cookie with a seed.
    what do you think about storing user.id and md5(user.password) in cookie and check?

  • speedyop

    seems hat i got some problems when using cookie component in localhost because of the domain.
    i(ve change the component like this
    if($this->_domain==”.localhost”){
    setcookie($this->_name.”$name”, $this->__encrypt($value), $this->_expire, $this->_path);
    echo $this->_name.”$name”.”#”.$this->__encrypt($value).”#”.$this->_expire.”#”.$this->_path.””;
    }else{
    setcookie($this->_name.”$name”, $this->__encrypt($value), $this->_expire, $this->_path, $this->_domain, $this->_secure);
    }

    is it normal?

  • cakebaker

    @all: Thanks for your comments.

    @Fred: Yes, you are right, at least if the user id is stored in plain text. But the cookie component encrypts the values by default, so it is probably not that easy to fake a user account (I don’t know how secure the used algorithm is).

    @Dieter@be: The scenario I had in mind as I wrote this article was a “remember me” functionality where the user is automatically logged in if a cookie is set.

    @speedyop: Yes, you are right, the cookie component is not in the current developer release.

    At the moment I don’t see much benefit in storing the hashed password in the cookie. If you force the user to enter a password you can validate it against the one stored in the database and so there is no need to store it in the cookie.

    Up to now I had no problems with the cookie component on localhost, but my local domains are in the form of myproject.localhost. If you think it is a bug, please open a ticket on trac (https://trac.cakephp.org).

  • Oli

    it would be usefull to set the $cookieKey in the config/core.php (like the CAKE_SESSION_STRING)

  • cakebaker

    @Oli: Yes, that could be useful. Please open an enhancement ticket on https://trac.cakephp.org/

  • Sarah

    I’ve been just started using the cookie component on a 1.1 development project and it works fine from a controller. I want to use it with my own User Authorisation Component and it seems to come unstuck there.

    I have to work out what’s going on and I’ll post at trac when I’ve got it sussed.

  • cakebaker

    @Sarah: I think it should be possible to use the cookie component within another component, even though I didn’t encounter a situation yet where that was necessary. Anyway, I hope you can figure out the issue, and good luck with the project :)

  • nate

    FYI, the API link you provided (which isn’t official anyway) is no longer responding. The official API docs are here: http://api.cakephp.org/1.2/class_cookie_component.html

  • cakebaker

    @nate: Thanks for the hint, I changed the link.

  • rtconner

    How do you specify the expiration date of the cookie?

  • cakebaker

    @rtconner: You can set the variable $cookieTime in your controller (time is in seconds).

  • emilk

    would like to report the same problem as speedyop 2007-01-21, 22:29 reports,
    i am on localhost apache and php

    his solution helps

  • cakebaker

    @emilk: Please open a ticket so that this issue can get fixed in the core. If you fix it in your installation, you probably overwrite it when there is a new release.

  • PD

    I want to set a cookie with a name ‘at’ and not have it as an array of any kind. How can I do that? When I pass name ‘at’ to the Cookie->write(), it writes a cookie with a name at[at].

  • cakebaker

    @PD: I think that’s not possible because of the way the component is implemented (have a look at the source). So you have to implement your own component resp. extend the existing component if you want this functionality.

    HTH

  • Jürgen Riemer

    @speedyop/emilk:
    using 127.0.0.1 also helps

  • cakebaker

    @Jürgen: Thanks for this hint!

  • Somebody

    The cookie spec requires two dots in the cookie domain — to prevent cookies using the domain “.com” or such. “.localhost” will fail because your browser will reject it.

  • cakebaker

    @Somebody: Thanks for the hint, I wasn’t aware of it, but it makes sense. And for those interested in the spec: http://wp.netscape.com/newsref/std/cookie_spec.html

  • Cristiano Betta

    Thank you for the documentation.

    Can you tell me how to keep my Cookie valid even if I close the browser?

  • Cristiano Betta

    Never mind, it was just some odd bug in my code that didnt make it live beyond browser closing.

  • cakebaker

    @Cristiano: I like problems which resolve themselves ;-)

  • Ceny Pozycjonowania Stron

    hi!,I love your writing so so much! share we keep up a correspondence more about your article on AOL? I need a specialist in this house to resolve my problem. May be that’s you! Looking forward to look you.

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License