This section describes the PHP Session Management API and Configuration parameters. We also discuss how to configure PHP to use sessions without cookies, and how PHP garbage collection removes old unused session files.
In this section we list the key functions used to build session-based applications in PHP. By accessing session variables using the $_SESSION array, you can write complete session-based applications using just four functions:
Creates a new session, or finds an existing one. Checks for a session ID in the HTTP request?either as a cookie or a GET variable named PHPSESSID. If a session ID isn't included in the request, or an identified session isn't found, a new session is created. If a session ID is included in the request, and a session isn't found, a new session is created using the session ID encoded in the request. When an existing session is found, the session variables are read from the session store and initialized. Using PHP's default settings, a new session is created as a file in the /tmp directory. This function always returns true.
Can be used in two ways: to return the session ID of an initialized session or to set the value of a session ID before a session is created. When used to return the session ID, the function must be called without arguments after a session has been initialized. When used to set the value of the session ID, the function must be called with the id as the parameter before the session has been initialized.
Removes the session from the PHP session management. With PHP's default settings, a call to this function removes the session file from the /tmp directory. Returns true if the session is successfully destroyed and false otherwise.
Initializes an existing session in read-only mode. This allows session variables to be read without PHP placing a write lock on the session store. This can improve performance if you expect simultaneous requests on the session; such is the case when a browser loads a HTML frame set and makes a parallel request for the framed pages.
PHP provides several functions that register variables in your code as session variables. Once registered, the values of these variables are tracked and automatically updated in the session store. However, as we have already shown, session variables can be set and accessed using the global array $_SESSION, and these functions need not be used. Also these functions should not be used if register_globals is disabled. We include a description of these functions because you are likely to find them used in older code:
Registers one or more variables in the session store. Each argument is the name of a variable, or an array of variable names. Once a variable is registered, it becomes available to any script that identifies that session. Registering variables with this function calls the session_start( ) code internally if a session has not been initialized. Returns true if registration is successful and false otherwise.
Returns true if the variable variable_name has been registered with the current session and false otherwise. Older code would use this function to test if a variable is registered to determine if a script has created a new session or initialized an existing one.
Unregisters the variable variable_name from the initialized session. Like the session_register( ) function, the argument is the name of the variable, not the variable itself. Unlike the session_register( ) function, the session needs to be initialized before calling this function. Once a variable has been removed from a session with this call, it is no longer available to other scripts that initialize the session. However, the variable is still available to the rest of the script that calls session_unregister( ). Returns true when the variable is unregistered and false otherwise.
Unsets the values of all session variables. This function doesn't unregister the actual session variables. A call to session_is_registered( ) still returns true for the session variables that have been unset.
While cookies are used in a large number of web sites around the world?including popular sites such as Amazon and Google?you may need to build session-based applications that don't rely on them. This section shows how your application code can pass the session ID encoded in the URL and avoid the need to set a cookie. We also discuss turning off cookies altogether. To begin, we look at what happens when cookie support is turned off.
A simple experiment that illustrates what happens when a user disables cookies is to request the script shown in Example 10-1 from a browser that has cookie support turned off. When repeated requests are made, the counter doesn't increment, and the session duration remains at zero seconds. Because a cookie isn't sent from the browser, PHP never looks for an existing session, but creates a new session each time the script is run. Some users configure their browsers to not accept cookies, so session-based applications should include an alternative communication mechanism.
Requests that don't contain the cookie can identify an existing session by setting the value of the session ID as a variable in the URL with the name PHPSESSID. For example, an initial request can be made to Example 10-1 with the URL:
http://localhost/example.10-1.php
This creates a session and its associated file.
Subsequent requests can be made that include the PHPSESSID in the URL as shown (we've truncated the session ID to fit on the page):
http://localhost/example.10-1.php?PHPSESSID=be20081806199800da22e24...
The response shows the counter set to 2 and the correct session duration. Repeated requests to this URL behave as expected: the counter increments, and the calculated duration increases.
If you write session-based applications to use the URL to identify sessions, the application doesn't fail for users who disable cookies. Applications can test if $_COOKIE["PHPSESSID"] is set and then start encoding the session ID in URLs, or just not use cookies at all.
Some browsers, such as Netscape, Mozilla, and Internet Explorer, share cookies across all windows or tabs that are running for the same user on the same machine. Because the cookies are shared, users cannot log into a web database application more than once and have independent sessions. If the session ID is stored in the URL, then this problem is solved.
There are some security issues with having the session ID encoded in the URL: session IDs can be stored in log files and bookmarks, and sessions can be shared amongst users. For example, if a users wants to share a session with another user, he can log in to the site and email the session URL to a friend who then has access to the session.
Scripts that generate embedded links to pages that use session variables need to include a GET attribute named PHPSESSID in the URL. This can be done using the basic PHP string support and calls to session_id( ). For example:
<?php // Initialize the session session_start( ); // Generate the embedded URL to link to // a page that processes an order $orderUrl = "/order.php?PHPSESSID=" . session_id( ); ?> <a href="<?php print $orderUrl ?>">Create Order</a>
To aid the creation of URLs that link to session-based scripts, PHP sets the constant SID to the session ID in a name=id format suitable to use as a URL query string. If no session has been initialized, PHP sets the value of SID to be a blank string. If a session is initialized, it sets the SID to a string containing the session ID in the form:
PHPSESSID=be20081806199800da22e24081964000
By including the value of SID when URLs are constructed, the hypertext links correctly identify the session. A link that points to a script that expects a session ID can be encoded like this:
<?php // Initialize the session session_start( ); ?> <a href="/order.php?<?php print SID;?>">Create Order</a>
As an alternative to writing code to formulate the session ID into the URL, PHP includes a URL rewrite feature that automatically modifies URLs embedded in HTML.
To activate this feature you need to set the parameter session.use_trans_sid in the php.ini file to 1. To activate the URL rewrite feature prior to PHP 4.2, the PHP source also needs to be configured with the ?enable-trans-id directive and then recompiled.
After URL rewrite is activated, PHP parses the HTML generated by scripts and automatically alters embedded URLs to include the PHPSESSID query string. PHP allows you to specify which URLs to be rewritten in the url_rewriter.tags parameter in the php.ini file.
The URL rewrite feature has the disadvantage that extra processing is required to parse every page generated by a PHP script, and modify embedded URLs.
PHP session management can be instructed not to set the PHPSESSID cookie by changing the session.use_cookies parameter to 0 in the php.ini file. The session configuration parameters in the php.ini file are described later in this section.
While it is good practice to build applications that provide a way to end a session? such as with a logout script that makes a call to session_destroy( )?there is no guarantee that a user will log out by requesting the appropriate PHP script. PHP session management has a built-in garbage collection mechanism that ensures unused session files are eventually cleaned up. This is important for two reasons: it prevents the directory from filling up with session files that can cause performance to degrade and, more importantly, it reduces the risk of someone guessing session IDs (more on this later) and hijacking an old unused session.
There are three parameters that control garbage collection: session.gc_maxlifetime, session.gc_probability, and session.gc_dividend, all defined in the php.ini file. A garbage collection process is run when a session is initialized, for example, when session_start( ) is called. The garbage collection process examines each session, and any sessions that have not been accessed for a specified period of time are removed. This period is specified as seconds of inactivity in the gc_maxlifetime parameter; the default value is 1,440 seconds, which is 24 minutes. The file-based session management uses the last access time of the file to determine if a session is to be destroyed.
|
The garbage collection process can become expensive to run, especially in sites with high numbers of users, because the last accessed time of every session file must be examined. The parameters gc_probability and gc_dividend set the percentage probability that the garbage collection process will check for timed-out sessions. If gc_probability is set to 1 and gc_dividend is set to 100?the default settings?garbage collection occurs with a probability of 1 in 100.[1] Setting gc_probability to 100 ensures that sessions are examined for garbage collection with every session initialization. Depending on the requirements, some figure between these two extremes balances the needs of the application and performance. Unless a site is receiving less than 1,000 hits per day, you should set the probability quite low. For example, an application that receives 1,000 hits in a 10-hour period with a probability set to 10%, runs the garbage collection function, on average, once every 6 minutes. Setting the probability of running the garbage collection too high adds unnecessary processing load on the server.
[1] Perhaps the gc_maxlifetime parameter should have been called gc_minlifetime, because the value represents the minimum time garbage collection permits an inactive session to exist. Remember that garbage collection is performed only when a request that initializes a session is made, and then only with the probability set by gc_probability.
Prior to PHP 4.3 probability was simply the value of gc_probability as a percentage; a value of 12 represented a 12% probability. The gc_dividend parameter allows probabilities to be set below 1%, which is useful for heavily loaded sites.
Several parameters can be manipulated to change the behavior of the PHP session management. These parameters are set in the php.ini file under the heading [Session].
This parameter specifies the method used by PHP to store and retrieve session variables. The default value is files, to indicate the use of session files as described in the previous sections. The other values that this parameter can have are: mm to store and retrieve variables from shared memory, and user to store and retrieve variables with user-defined handlers. In Appendix F we show you how to create your own handlers to store session variables in a MySQL database. We don't recommend using the mm shared memory approach, as locking isn't correctly implemented to avoid the transaction problems discussed in Chapter 8.
This parameter specifies the directory in which session files are saved when the session.save_handler is set to files. The default value is the temporary directory, /tmp. On Unix systems, you may want to use a directory only accessible to the owner of the Apache process to prevent other users reading session files. For Microsoft Windows systems, you will need to change this to an appropriate path. The specified directory must exist.
As of PHP 4.0.1, you can modify the save path to store session files in deeper level sub-directories. This can improving efficiency for operating systems that don't perform well with large numbers of session files in a single directory. We don't discuss this in detail.
This parameter determines if PHP sets a cookie to hold the session ID. Setting this parameter to 0 stops PHP from setting cookies and may be considered for the reasons discussed in the previous section. The default value is 1, meaning that a cookie stores the session ID.
When this parameter is set to 1 PHP is prevented from overwriting the session ID set from a cookie with the value from URL, thereby improving the security of an application. This parameter was introduced in PHP 4.3 and has a default value of 0, which is also the default behavior in earlier versions of PHP. However, if you use this parameter and cookies are not enabled in sessions or in a user's browser, then sessions will not be able to be used.
This parameter controls the name of the cookie, GET attribute, or POST attribute that is used to hold the session ID. The default is PHPSESSID, and there is no reason to change this setting unless there is a name collision with another variable.
With the default value of 0 for this setting, PHP initializes a session only when a session call such as session_start( ) or session_register( ) is made. If this parameter is set to 1, sessions are automatically initialized if a session ID is found in the request. Allowing sessions to autostart adds unnecessary overhead if session values aren't required for all scripts.
This parameter holds the life of a session cookie in seconds and is used by PHP when setting the expiration date and time of a cookie. The default value of 0 sets up a session cookie that lasts only while the browser program is running. When a user quits their browser, their session is destroyed (and the user is logged out of the application).
Setting this value to a number of seconds other than 0 sets up the cookie with an expiration date and time. The expiration date and time of the cookie is set as an absolute date and time, calculated by adding the cookie_lifetime value to the current date and time on the server machine.[2]
[2] The actual expiration of the cookie is performed by the browser, which compares the expiration date and time of the cookie with the client machine's date and time. If the date and time are incorrectly set on the client, a cookie might expire immediately or persist longer than expected.
This parameter sets the valid path for a cookie. The default value is /, which means that browsers include the session cookie in requests for resources in all paths for the cookie's domain. Setting this value to the path of the session-based scripts can reduce the number of requests that need to include the cookie. For example, setting the parameter to /winestore on a server hosting the www.webdatabasebook.com domain instructs the browser to include the session cookie only with requests that start with http://www.webdatabasebook.com/winestore/.
This parameter can override the domain for which the cookie is valid. The default is a blank string, meaning that the cookie is set with the domain of the machine running the web server, and the browser includes the cookie only in requests sent to that domain.
This parameter sets the secure flag of a cookie, which prevents a browser from sending the session cookie over non-encrypted connections. When this setting is 1, the browser sends the session cookie only over a network connection that is protected using the Secure Sockets Layer, SSL. Setting this parameter to 1 only makes sense when you have configured your Web server to use SSL. We discuss SSL in the next chapter and show how to install and configure Apache with SSL for Unix platforms in Appendix A-Appendix C. The default value of 0 allows a browser to send the session cookie over encrypted and non-encrypted services. This parameter was added in PHP 4.0.4.
This parameter sets up the method by which variables are serialized, that is, how they are converted into a stream of bytes suitable for the chosen session store. The default value is php, which indicates use of the standard PHP serialization functions. An alternative is wddx, which uses the WDDX libraries that encode variables as XML; the library is described in Appendix G.
The probability that the garbage collection process will be performed when a session is initialized is the value of gc_probability divided by the value of gc_dividend. The default values of 1 and 100 result in a 1% chance of garbage collection each time the collector runs. See the discussion in the previous section for a full explanation of garbage collection.
This parameter sets the life of a session in number of seconds. The default value is 1440, or 24 minutes. Garbage collection destroys a session that has been inactive for this period. See the discussion in the previous section for a full explanation of garbage collection.
This parameter can restrict the creation of sessions to requests that have the HTTP Referer header field set. This is a useful feature if access to an application is allowed only by following a hypertext link from a particular page, such as a welcome page. If the HTTP Referer header of a request that is external to the host doesn't contain the value of this parameter, PHP creates a session, but the session is marked as invalid and unusable. Subsequent requests will fail to initialize session variables from the session. The default value of a blank string applies no restriction.
PHP generates the session IDs from a random number seeded by the system date and time. Because the algorithm is known?it can be looked up in the PHP source code?it makes guessing session IDs a little easier. If this parameter is set to the name of a file, the first n bytes from that file (where n is specified by the session.entropy_length parameter) are used to seed the random number generator, making the ID less predictable. The default value is left blank, meaning the default seeding method is used. On Unix systems, an alternative is to use /dev/urandom, a special Unix device that produces a pseudo-random number.
This parameter is the number of bytes to use when generating a session ID from the file specified by session.entropy_file. The default value of 0 is required when no entropy file is set.
This parameter controls how clients and proxy servers cache responses. Web applications?and especially session-based web applications?can be adversely affected when pages are cached. The default value of nocache prevents caching in both clients and proxy servers. Setting this parameter to public allows caching in both clients and proxy servers, while the value of private allow caching in the client only. PHP 4.2 allows the value private_no_expire in this parameter, which avoids problems in some browsers when the Expire header field is used to control caching. See Appendix D for more details about HTTP caching.
This parameter is used when caching is allowed; it sets the expiration date and time of the response to be the current system time plus the parameter value in minutes. The default value is 180.
Prior to PHP 4.2, session variables could be initialized in the global scope, even when register_globals was disabled. While this is considered a bug, PHP allows code written with this behavior to run with bug_compat_42 set to 1 and provides warnings with bug_compat_warn set to 1 (the default values). Setting these parameters to 0 turns off compatibility and warnings respectively. If you are writing new code, we recommend that bug_compat_42 is set to 0.