Let’s eat cake and cookies

Published on January 20, 2007 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']);

26 comments baked

  • KesheR January 20, 2007 at 13:05

    Thxxxxx

  • speedyop January 20, 2007 at 21:47

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

  • Fred January 21, 2007 at 01:25

    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 January 21, 2007 at 11:37

    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 January 21, 2007 at 12:27

    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 January 21, 2007 at 22:29

    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 January 22, 2007 at 10:03

    @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 February 16, 2007 at 18:03

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

  • cakebaker February 17, 2007 at 11:09

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

  • Sarah February 24, 2007 at 14:29

    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 February 24, 2007 at 20:05

    @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 April 13, 2007 at 16:31

    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 April 13, 2007 at 17:14

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

  • rtconner May 04, 2007 at 22:23

    How do you specify the expiration date of the cookie?

  • cakebaker May 05, 2007 at 18:52

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

  • emilk June 10, 2007 at 22:14

    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 June 12, 2007 at 18:55

    @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 July 18, 2007 at 03:16

    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 July 19, 2007 at 16:35

    @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 December 07, 2007 at 11:55

    @speedyop/emilk:
    using 127.0.0.1 also helps

  • cakebaker December 11, 2007 at 08:42

    @Jürgen: Thanks for this hint!

  • Somebody January 14, 2008 at 19:18

    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 January 16, 2008 at 12:27

    @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 January 28, 2008 at 02:19

    Thank you for the documentation.

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

  • Cristiano Betta January 28, 2008 at 02:37

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

  • cakebaker January 29, 2008 at 17:16

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

Bake a comment




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

© daniel hofstetter. Licensed under a Creative Commons License