torstai 2. heinäkuuta 2009

Remember me? Using cookies to remember login longer

There's been a lot of great tutorials on login pages and allmost every aspect has been covered. This tutorial will show you how to give your user the option to stay logged in using cookies.

Introduction

I won't be going too deep into the anatomy of a login page, since there's more than enough good tutorials covering that already. Instead I'll just show you how to use cookies to remember login data.


Here's the page we'll be using. Nothing fancy this time.




Step 1 - The page


Well make just a basic html page. This tutorial is not about how to make a good login page so please don't concentrate too much on the irrelevant things.



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>Remember me?</title>
</head>
<body>
<h1>Secret page</h1>
<?php echo $contens; ?>
</body>
</html>


Step 2 - The PHP


Append in the top of the page the following lines of PHP.



<?PHP
session_start();

In every login system it's necessary to call for the session start before anything else get's sent to the users browser.
The same this goves to cookies by the way.
Since they'r also sent inside the header call, it's important that nothing other that header info is sent before them.



if(isset($_GET['do']))
{
if($_GET['do'] == "logout")
{
unset($_SESSION['loggedin']);
setcookie('uvSavePass', "", time()-2592000);
}
}

Before checking the cookies, sessions, or login information, we must give the application the option to unset the logged in state.
Otherwise we'll end up doing all the login checks for nothing.


If the user has requested to be logged out, we unset the session variable and set the cookie to be valid until some time in the past.
So we are setting the same cookie, we can't directly just delete it from the users computer.
Instead we simply set it's best before date to be in the past so the users browser knows to get rid of it automatically.



if ( !isset($_SESSION['loggedin']) )
{
if ( isset( $_POST['dologin'] ))
{
$username= htmlspecialchars($_POST['username'], ENT_QUOTES);
$password = htmlspecialchars($_POST['password'], ENT_QUOTES);
$result = ($username == "joe" && $password == "123");
if ($result != false)
{
if ( $_POST['rememberme'] == "on" ){
$cookie = base64_encode(serialize(array('uname'=>$username,'password'=>$password)));
try
{
setcookie('uvSavePass', $cookie,time()+2592000);
}
catch (Exception $error)
{
$contens = "Error saving cookie: $error";
}
}
$_SESSION['loggedin'] = true;
$contens .= "<p>Welcome to the site.</p><p><a href=\"?do=logout\">Click here</a> to log out</p>";
}
else
{
$contens = "Incorrect username or password!";
$contens .= '
<form method="post" action="?do=login">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="checkbox" name="rememberme" value="on" /> Remember me?<br />
<input type="submit" name="submit" value="Log in" />
<input type="hidden" name="dologin" value="true" />
</form>
';
}
}


If the session is not yet set (i.e. the user is visiting for the first time, the first time since logging out, or after such a long period that the session has expired) we'll check for two things.
First, shown here, we check if the user has submitted the login form.
If the login information is correct (change the variable comparison to use a database in your application) we set the session variable.
If the Remember me? checkbox was checked we set a cookie with base64 encoded login information and set it's lifetime to time + 1 month.
It is true that this way someone can hack the password from the cookie if one would gain access to the user's computer, but since many people save their login information into the browsers remember password functionality, this is at least no more insecure.



else if ( isset($_COOKIE['uvSavePass']))
{
$u = unserialize(base64_decode($_COOKIE['uvSavePass']));
$result = ($u['uname'] == "joe" && $u['password'] == "123");
if ($result != false)
{
$_SESSION['loggedin'] = true;
$contens .= "<p>Welcome to the site.</p><p><a href=\"?do=logout\">Click here</a> to log out</p>";
}
}

Ok, so the user hasn't posted the form.
Now we must perform the secons check to see if a cookie exists.
If it does and it's contents are correct, we set the session variable to true.



else
{
$contens .= "<p>Please log in.</p>";
$contens .= '
<form method="post" action="?do=login">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="checkbox" name="rememberme" value="on" /> Remember me?<br />
<input type="submit" name="submit" value="Log in" />
<input type="hidden" name="dologin" value="true" />
</form>
';
}
}
else
{
$contens .= "<p>Welcome to the site.</p><p><a href=\"?do=logout\">Click here</a> to log out</p>";
}
?>

And if the cookie is not found we'll show the user the login form.
The final else segment is visited if the session is already set and is still valid.


I'm using the WebDeveloper toolbar for Firefox.
It shows me the cookies that were sent and their content.
If everythig was set correctly we should see something like this when choosing the Remember me? option on login.




Conclusions


This has been a small tutorial on how to implement cookies on login forms. Hope you have enjoyed ant learnt something new. Thanks for reading!

Ei kommentteja:

Lähetä kommentti