Recipe 8.10. Using Cookie Authentication


8.10.1. Problem

You want more control over the user login procedure, such as presenting your own login form.

8.10.2. Solution

Store authentication status in a cookie or as part of a session. When a user logs in successfully, put her username in a cookie. Also include a hash of the username and a secret word so a user can't just make up an authentication cookie with a username in it, as shown in Example 8-23.

Using cookie authentication

<?php $secret_word = 'if i ate spinach'; if (pc_validate($_POST['username'],$_POST['password'])) {     setcookie('login',               $_POST['username'].','.md5($_POST['username'].$secret_word)); } ?>

8.10.3. Discussion

When using cookie authentication, you have to display your own login form, such as the form in Example 8-24.

Sample cookie authentication login form

<form method="POST" action="login.php"> Username: <input type="text" name="username"> <br> Password: <input type="password" name="password"> <br> <input type="submit" value="Log In"> </form>

You can use the same pc_validate( ) function from Example 8-18 to verify the username and password. The only difference is that you pass it $_POST['username'] and $_POST['password'] as the credentials instead of $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW']. If the password checks out, send back a cookie that contains a username and a hash of the username, and a secret word. The hash prevents a user from faking a login just by sending a cookie with a username in it.

Once the user has logged in, a page just needs to verify that a valid login cookie was sent in order to do special things for that logged-in user. Example 8-25 shows one way to do this.

Verifying a login cookie

<?php unset($username); if ($_COOKIE['login']) {     list($c_username,$cookie_hash) = split(',',$_COOKIE['login']);     if (md5($c_username.$secret_word) == $cookie_hash) {         $username = $c_username;     } else {         print "You have sent a bad cookie.";     } } if ($username) {     print "Welcome, $username."; } else {     print "Welcome, anonymous user."; } ?>

If you use the built-in session support, you can add the username and hash to the session and avoid sending a separate cookie. When someone logs in, set an additional variable in the session instead of sending a cookie, as shown in Example 8-26.

Storing login info in a session

<?php if (pc_validate($_POST['username'],$_POST['password'])) {     $_SESSION['login'] =         $_POST['username'].','.md5($_POST['username'].$secret_word)); } ?>

The verification code, shown in Example 8-27, is almost the same; it just uses $_SESSION instead of $_COOKIE.

Verifying session info

<?php unset($username); if (isset($_SESSION['login'])) {     list($c_username,$cookie_hash) = explode(',',$_SESSION['login']);     if (md5($c_username.$secret_word) == $cookie_hash) {         $username = $c_username;     } else {         print "You have tampered with your session.";     } } ?>

Using cookie or session authentication instead of HTTP Basic authentication makes it much easier for users to log out: you just delete their login cookie or remove the login variable from their session. Another advantage of storing authentication information in a session is that you can link users' browsing activities while logged in to their browsing activities before they log in or after they log out. With HTTP Basic authentication, you have no way of tying the requests with a username to the requests that the same user made before they supplied a username. Looking for requests from the same IP address is error prone, especially if the user is behind a firewall or proxy server. If you are using sessions, you can modify the login procedure to log the connection between session ID and username using code such as that in Example 8-28.

Connecting logged-out and logged-in usage

<?php if (pc_validate($_POST['username'],$_POST['password'])) {     $_SESSION['login'] =         $_POST['username'].','.md5($_POST['username'].$secret_word));     error_log('Session id '.session_id().' log in as '.$_REQUEST['username']); }

Example 8-28 writes a message to the error log, but it could just as easily record the information in a database that you could use in your analysis of site usage and traffic.

One danger of using session IDs is that sessions are hijackable. If Alice guesses Bob's session ID, she can masquerade as Bob to the web server. The session module has two optional configuration directives that help you make session IDs harder to guess. The session.entropy_file directive contains a path to a device or file that generates randomness, such as /dev/random or /dev/urandom. The session.entropy_length directive holds the number of bytes to be read from the entropy file when creating session IDs.

No matter how hard session IDs are to guess, they can also be stolen if they are sent in clear text between your server and a user's browser. HTTP Basic authentication also has this problem. Use SSL to guard against network sniffing, as described in Recipe 18.13.

8.10.4. See Also

Recipe 8.9; Recipe 8.9 discusses logging errors; Recipe 20.9 discusses verifying data with hashes; documentation on setcookie( ) at http://www.php.net/setcookie and on md5( ) at http://www.php.net/md5.




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net