HTTP is stateless. It means that on every request you make to a website it will have completely forgotten about your previous request. But how does a server remember then that you have already logged in at one point? Somehow a browser session must be linked to some stored information on a server. In PHP, solutions are provided with sessions and cookies.

When a user first visits a website the server creates a session together with a so-called session ID. This session ID is sent back to the browser in one of the headers and the browser then stores the session ID as a so-called cookie. On the subsequent requests to the server the browser sends this session ID again as one of the headers back to the server so that the server can look up the corresponding session. The session can then be filled with useful information such as the login status.

In terms of PHP code the session starts with session_start(). A call to this method will define a session ID (a random string like 365fe8f9677a68a149f442a9cc735961) and will create a small text file with as file name the same session ID prefixed with “session_” as in “session_365fe8f9677a68a149f442a9cc735961”. This file usually resides in the /tmp folder. The session ID is also sent to the browser as a response header and the browser stores the ID as a cookie with name PHPSESSID and as value the session ID.

Where the browser physically stores a cookie depends on the particular brand and operating system. In Internet Explorer cookie files may be found in C:\Users\username\AppData\Roaming\Microsoft\Windows\Cookies. Firefox stores cookies in a sqlite database.

Session management then starts with session_start() although it is possible a session has auto started by the server. Check the check session value session.auto_start in the php.ini file or via phpinfo(). If the value is 1 then the server will create a session on every request for you. The default value is 0 and can only be changed in the php.ini file, in a .htaccess file, in the httpd.conf or .user.ini (PHP_INI_PERDIR) but not via a ini_set() method.

in a .htaccess file add:

php_flag session.auto_start 0

Now start a new session and echo the session id:

session_start();
 echo session_id();

The session id is now displayed on screen for example as 365fe8f9677a68a149f442a9cc735961, a cookie is also set having the name PHPSESSID and with value (or content if you like) the same session id.To actually see cookie information in a browser use a web development tool like Firebug (hit F12). At the same time over in the /tmp folder of the server a new file has been created with as filename the same id (prefixed by sess_) but without any content. The manner in which a session is stored (here the filesystem) is determined by session.save_handler variable. An alternative to files is session storage in a database.

The file location is set by session.save_path as in

ini_set('session.save_path', '/your/local/dir/sessions');
 

You can move this folder to your own virtual host in this way, in a virtual hosting environment the /tmp folder is not a safe place. Make sure the folder is owned by group Apache and that the group can write to this folder (775 settings).

so how is this all helpful? The user’s browser is now linked to a small file on the server that can now be filled with data on that user. This information will persist on repeated requests from that user. On every request to the server the browser will send along this header:

Cookie	PHPSESSID=e98ba332281d37130ba2adc466148006
  

The cookie id can then be compared with the session id in the session folder. Adding information is as simple as

 if(!isset($_SESSION['START_TIME'])){
 $_SESSION['START_TIME'] = date('Y-m-d h:i:s');
}
echo "User first accessed this page: " . $_SERVER['START_TIME'];
 

The $_SESSION variable is a so-called global variable. This information is stored by serialisation as

START_TIME|s:19:"2014-05-06 02:49:08";
 

For each user the time the user first accessed the page is now stored in a session and can be retrieved from the session on any new request.

Things to try out. Try requesting the same page from a different browser, the session now holds two session files one for each user but with personalised information. Try destroying the session session and then repeat the request: you will see the server session is recreated with the same filename but the original content of the file has been destroyed. Try destroy the cookie: a new session id is returned from the server and the content is refreshed.

No cookies? Disable the cookies in the browser preferences and destroy the existing cookies. On every request a new session ID is generated and the session content is continuously refreshed. No cookie is set. Can you still use sessions without cookies? Yes.

ini_set("session.use_cookies",0);
ini_set("session.use_only_cookies",0);
ini_set("session.use_trans_sid",1);
session_start();
 

In this configuration the session ID can also be appended to the url as in test.php?PHPSESSID=953ce493162a4c9adcdc56fc3341fad9 and the session is remembered and is persistent as before. This method is not considered very safe though.

Other uses for cookies? Yes, more information can be stored on the user’s browser with additional cookies:

setcookie('language','EN');


this will set an additional cookie with name “language” and value “EN”

On every request this user setting can be retrieved via

 echo $_COOKIE['language'];
 


where $_COOKIE is another global variable just like $_SESSION. This language setting could also have been set in the session but note that when you remove the session on the server the information stored in the cookie is still available.

How to destroy information. Sometimes you want to manage the lifetime of cookies and sessions.
The lifetime of a cookie can be set by

 
setcookie('language','EN', time() + 10);
 


The expiration date of the cookie changes from “session” to the exact time of expiration which is now plus 10 seconds. How to set the expiration time of the PHPSESSID cookie? It is not set by setCookie() but by session_start(). Solution


ini_set('session.cookie_lifetime', 10);

Now every ten seconds a new session id is generated. It is possible to refresh the cookie each time a new request is made with an existing cookie: after session_start() overwrite the PHPSESSID cookie with a new timestamp.

 
session_start();
if( session_id() == $_COOKIE['PHPSESSID']){
   setcookie(session_name(),session_id(),time() + 10);
}


Now even though the cookie is set to last for just 10 seconds , the cookie will be refreshed as long requests are repeated in under ten seconds.

Want to destroy the server-side session instead? This can be done immediately via session_destroy(). A less transparent method is called session garbage collection.

// lifetime 10 seconds
ini_set('session.gc_maxlifetime', 10);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

Garbage collection takes place on every call to session_start(). The maximum lifetime of a session can be set with session.gc_maxlifetime and if the session is expired the garbage collection process will clean it up. Garbage collecting is a burden to the server (every file has to be opened in order to see the timestamp) cleaning should be done every once in a while. That is where probability and the divisor come in. A ratio of 0.01 means actual garbage collection will take place in 1% of all requests (nobody knows why gc_probability is called like that by the way). Garbage collection is important because otherwise the sessions files left by users to a a website will just accumulate.

Advertisements