Here is how I do it.
First of all, the login form should transmit data using POST, not GET. This keeps the username/password from showing up in the Location: field of the browser.
With data in hand, I look up the username and password from the database. If they match, I use this function:
function makehashid()
{
global $cryptphrase;
global $uid;
return md5("$cryptphrase $uid");
}
... to compute a magic encrypted key for the user. This key is stored as a session variable (server side) along with the userid itself. The reason for this will be explained shortly.
On every secured page, I do this:
// function to validate whether a current, valid uid exists
function isloggedin()
{
global $uid;
global $hashid;
return ($hashid == makehashid($uid));
}
... and if the function returns FALSE, I forcibly log the user out and kick him to the login page.
Here's why I do this: I don't want some net.moron to be able to pass false UID information to my server by adding a string to a URL. So I have created a secret checksum that makes the session invalid if the UID is changed.
The net.moron can't include fake hashid information in the URL, because the MD5 value is computed using a secret cryptphrase, which comes from my server configuration.
The important points here are:
- PHP sessions are used to store the login tokens server-side, and they are not shipped back and forth over the wire.
- The only thing that gets stored in a cookie (or sent in a URL, if cookies are disabled) is the PHP-generated unique session identifier, which is an unpredictable value.
- Everything is reasonably secure.