PHP cookies and session – about the implementation

Teaching of a Samurai Engineer 8: Cookies and Sessions, part 2 (Implementation: Cookies)

Last time, we mostly looked at the difference between cookies and sessions (relating to PHP-provided sessions.
This time, let’s go a bit heavy on the code, and learn about things to watch out for during implementation.

Last time, we mostly looked at the difference between cookies and sessions (relating to PHP-provided sessions.
This time, let’s go a bit heavy on the code, and learn about things to watch out for during implementation.
First, whether for cookies or sessions, at the end you will output a Cookie (HTTP response header).
Thus, while it depends on your php. ini’s settings (output_buffering), writing code like below can get you an error that reads ‘Warning: session_start (): Cannot start session when headers already sent in’ or ‘Warning: Cannot modify header information — headers already sent by’.

var_dump [ini_get (’output_buffering’) ];
setcookie (’name’. ’value’); // This part is the problem

var_dump [ini_get (’output_buffering’) ];
session_start (); // This part is the problem

If ini_get (‘output_buffering’) is 0, you will get a warning.
To summarise a bit, this is because before the headers are outputted, the contents (HTTP response body) have already been outputtedn (I plan to write about this in more detail another time). output_buffering is PHP_INI_PERDIR, and so it becomes an entry you can configure in php. ini, .htaccess, httpd.conf or user. ini (if PHP 5.3 or later)

This is something you can confirm every time you develop in a new environment, but you can also prevent it by writing the following in the program.

ob_start (); // This part is key
var_dump [ini_get (’output_buffering’) ];
setcookie (’name’. ’value’);
ob_end_flush (); // This part is key

ob_start (); // This part is key
var_dump [ini_get (’output_buffering’) ];
session_start ();
ob_end_flush (); // This part is key

ob_start () and ob_end_flush () are Output Control Functions, so using functions like this frequently is an easy way to prevent accidents.

Now let’s look at implementation for cookies.
First, inserting a value into the cookie. As written in the code above, setting a value for a cookie uses the setcookie () function.

ob_start ();
setcookie (’name’. ’value’);
// and so on

Cookies cannot be used right after insertion, so you will need to be careful.
ob_start ();
setcookie (’hoge’, ’foo’);
var_dump ($_COOKIE[’hoge’]); // XXX You can’t use this.
// and so on

If you want something that configures cookies, and can use that configured value in later code, then:
$hoge = ’foo’;
setcookie (’hoge’, $hoge);

In short:

  • First inserting this as a variable
  • Then making the secondary parameter for setcookie a variable

…Is the way to do it. Now for the value to insert. Note that only lines of text can be specified as a value in a cookie. You cannot specify arrays, instances, or true/false values (they will be cast as strings), so be careful.
Typically if you want to insert an array, you use json_encode to make it a row of text.

ob_start ();
setcookie (’string’, ’sss’); // OK
setcookie (’int’, 111); // It’s cast as a string and inserted as ‘111 ’
setcookie (’int’, 111); // ‘True’ is cast as a string and becomes ‘1 ’
setcookie (’int’, 111); // ‘True’ is cast as a string and the bool_false key itself disappears
setcookie (’int’, 111); // The array is cast as a string and becomes a row of text that reads ‘array’
setcookie [’json’, json_encode ([0, 1, 2 ]) ); // A suitably json-encoded text row ges in (when you use it, use json_decode () to make it an array again]
setcookie (’object’, new stdClass); // Generate a recoverable fatal error
// and so on

Furthermore, making arrays and instances into letters might make some people think of serialize () functions. However, if you use a serialize () function for a cookie, it links directly to security risks such as insecure deserialization or object injection, so you MUST never use this method.

Always remember that cookies can be easily altered by the user. One more thing. Cookies have a limit on their length. According to RFC 6265, the following is listed as the size browsers are supposed to support.

  • (Total of name, value and type) at least 4096 bytes per cookie
  • At least 50 cookies per domain
  • At least 3000 cookies over the whole browser

In other words, you need to remember that numbers over what is listed above may not be supported.Or to summarise, you can’t set really large amounts of numbers or long rows of letters.
As I wrote above, cookies are something stored on the user’s local storage, and information sent by HTTP request. In other words, something the user can easily rewrite.
As such, you should always be doing a minimum of validation. There are several ways to wipe set values for cookies.

  • Set the cookie’s lifespan to a very long age.
  • Insert empty space (or NULL) for the value (if using PHP, program to add ‘=delete’ to the name (confirm on php-7.3.11) )

Thus, code like something below is usually recommended.
ob_start ();
setcookie [’hoge’, ’’, time () — 60 *60 *24 *365];
// and so on

Writing by the method below won’t be deleted, so be careful.
unset ($_COOKIE[’hoge’]); // XXX This doesn’t work
// and so on

Finally, let’s look at some common parameters for setcookie () that can be abbreviated.
First off, the third parameter, expire (expiry date). Typically this means the limit on when the cookie’s data is effective. However, by abbreviating it or deliberately setting it to 0, you create a cookie that’s effective until the browser closes.
Cookies that disappear once the browser closes are known as temporary or session cookies.
The fourth parameter is path. This depends partly on site composition too, but if you don’t specify, then a cookie one page could read will be unreadable for another (because the value changed), so it’s relatively important. This depends on the site structure too, but it’s relatively common to specify.
The fifth parameter is integer, and rarely specified, so don’t worry about it too much.
The sixth is secure, and particularly important these days. If it’s an https site, you can set it to ‘always true’.
The seventh is ‘httponly’, where there’s a sort of gentlemen’s agreement that while it’s not absolutely safe, on a standard browser, it will mostly stop access from JavaScript to cookies, and so there’s no harm setting it to true.
As you can see, setcookie () has several patterns of parameter use. Think about it for a while at least once, and try to imagine a couple common patterns you might use often.

What I personally use often is shown below.

// Temporary cookies
setcookie (’name’. ’value ’, 0, ’/’, ’’, true, true);
// Cookies with temporary effectiveness (e. g. one day)
setcookie [’name’, ’value’, time () + 60 *60 *24, ’/’, ’’, true, true];
// Deleting cookie value
setcookie [’name’, ’’, time () — 60 *60 *24 *365, ’/’, ’’, true, true];

This time, we looked at implementation of cookies.
Next time, I’ll write about implementing sessions.

Part 1

Part 2

Part 3

Part 4

Part 5

Part 6

Part 7

Part 9

Michiaki Furusho