Building Browsergames: The Login Page (PHP)

Building off of where we left off, today we will be building the login page for our browsergame.

To begin with, let’s modify our users table, and add two more columns – we will be tracking which users are administrators, and what time a particular user last logged in at:

pALTER TABLE `users` ADD `is_admin` tinyint(1) NOT NULL DEFAULT '0';
ALTER TABLE `users` ADD `last_login` timestamp NULL;

By running the SQL above, we added two new columns to our users table – users.is_admin, and users.last_login. users.is_admin is of the type tinyint, because we will be using it to flag which users are administrators or not – which will become important once we finish our authentication system and move on to things like the Admin control panel.

users.last_login is a timestamp, because we will be using it to keep track of the last time that the user logged in at. Our login script will update this, whenever the user logs in.

Alright, that’s enough database changes. Let’s move on to the actual code!

To begin with, we set up our form. Pretty simple stuff:

 

<form action='login.php' method='post'>
Username: <input type='text' name='username' /><br />
Password: <input type='password' name='password' /><br />
<input type='submit' value='Login' />
</form>

All we’ve done here is create an ultra-basic login form. But now that we’ve done that, we can begin to add our logic to the page. First off, let’s add a check to make sure that there’s data being sent to the page:

 

<?php
	if($_POST) {
		// do processing here
	}
?>
<form action='login.php' method='post'>
Login pages are actually very simple – even simpler than the registration page! Here’s what the pseudocode for a login page looks like:

if(username/password combination matches on in the database) {
	log user in	
} else {
	login error	
}

So, with that being said, let’s do the username/password check using the values sent to us from our form(and the configuration file we built earlier for connecting to the database):

 

require_once 'config.php';	// this is from our earlier article on configuration files in PHP
		$username = $_POST['username'];
		$password = $_POST['password'];		
		$conn = mysql_connect($dbhost,$dbuser,$dbpass)
			or die ('Error connecting to mysql');
		mysql_select_db($dbname);
		$query = sprintf("SELECT COUNT(id) FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
			mysql_real_escape_string($username),
			mysql_real_escape_string(md5($password)));
		$result = mysql_query($query);
		list($count) = mysql_fetch_row($result);
		if($count == 1) { ?>
<span style='color:green'>Login Successful.</span>
<?php	} else {	?>
<span style='color:red'>Error: that username and password combination does not match any currently within our database.</span>
<?php	}
	}

That looks like a lot of code, but it’s almost the same code as what we built for our registration page earlier. We check to see how many users exist within the database with the same username and password as the user is attempting to log in with. Because we used the md5() function on our password in our registration code, we will also need to use it in our login code – otherwise, our test will not work – because the passwords will never match.

Once we’ve created our query and executed it, we retrieve the count of users that have matching characteristics(the same username, the same hashed password value) – as long as it’s one, we know that the values matched – and therefore, the user’s data is correct and we can log them in. If the count isn’t 1, then the data didn’t match – which means their information was incorrect. So we show them a helpful error message to tell them what went wrong.

However, this doesn’t do any of the ‘dirty’ work of logging users in – that is, storing a cookie with their data in it, and redirecting them to a different page. First off, let’s add the cookie storage, by using PHP’s session object. To begin with, we need to change the top of our login script to start up our session using session_start():

session_start();	// start up our session - or recreate it if it already exists
	if($_POST) {

Then, we will be able to store our information into the session for the current user, after they have logged in. We’ll be doing that in the area where we were previously displaying a “login successful” message:

if($count == 1) {
			$_SESSION['authenticated'] = true;
			$_SESSION['username'] = $username;
		?>

<span style=’color:green’>Login Successful.</span>
And that will store the data for the user into their unique session.

When we store a user’s data into the $_SESSION variable, we tell PHP that we’d like it to persist – this way, if the user visits another page where they might be required to login, we can easily check if they are logged in using a small snippet:

session_start();
if($_SESSION['authenticated'] != true) {
	// not logged in!	
} else {
	// do other stuff here	
}

Which means that for our later pages where we need to do those sorts of checks, we’ll have an easy time at that.

We still haven’t done any of the neat things we wanted to made our database modifications for, however. First off, whenever a user successfully logs in we’ll update the value we have stored for their last successful login:

 

$query = sprintf("UPDATE users SET last_login = NOW() WHERE UPPER(username) = UPPER('%s') AND password = '%s'",
				mysql_real_escape_string($username),
				mysql_real_escape_string(md5($password)));
			mysql_query($query);
		} else {	?&gt;
&lt;span style='color:red'&gt;Error: that username and password combination does not match any currently within our database.&lt;/span&gt;

That brief snippet of code will allow us to update the user’s last logged in date – to whatever time it is currently. We run it using mysql_query() without storing the return value because it’s an UPDATE query – it won’t return any sort of meaningful data other than whether it executed successfully or not.

You may have noticed that line 22 has changed slightly – it no longer has the closing ?> tag. That’s because we will be adjusting our code to redirect the user, based on whether or not they’re an administrator:

$query = sprintf("SELECT is_admin FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
				mysql_real_escape_string($username),
				mysql_real_escape_string(md5($password)));
			$result = mysql_query($query);
			list($is_admin) = mysql_fetch_row($result);
			if($is_admin == 1) {
				header('Location:admin.php');	// redirect to admin page
			} else {
				header('Location:index.php');	// redirect to normal index page
			}
		} else {	?&gt;

This code is pretty basic. We just retrieve the value of is_admin, and then check to see what it is. If it’s 1, they’re an administrator – and we redirect them to the special admin-only page. If it’s 0, they’re a regular user – so we send them to the normal home page(in this case, index.php).

That’s really all there is to a login page – they’re a pretty simple piece of functionality to build into your game. We’ve built off of the basic login page and added a little bit of extra stuff – like tracking the last time the user logged in, and redirecting them to a different place based on whether they’re an administrator. But when you get down to the core it, a login page is a login page. Here’s all of the code we wrote in one place for you:

 

&lt;?php
	session_start();
	if($_POST) {
		require_once 'config.php';
		$username = $_POST['username'];
		$password = $_POST['password'];		
		$conn = mysql_connect($dbhost,$dbuser,$dbpass)
			or die ('Error connecting to mysql');
		mysql_select_db($dbname);
		$query = sprintf("SELECT COUNT(id) FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
			mysql_real_escape_string($username),
			mysql_real_escape_string(md5($password)));
		$result = mysql_query($query);
		list($count) = mysql_fetch_row($result);
		if($count == 1) {
			$_SESSION['authenticated'] = true;
			$_SESSION['username'] = $username;
			$query = sprintf("UPDATE users SET last_login = NOW() WHERE UPPER(username) = UPPER('%s') AND password = '%s'",
				mysql_real_escape_string($username),
				mysql_real_escape_string(md5($password)));
			mysql_query($query);
			$query = sprintf("SELECT is_admin FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
				mysql_real_escape_string($username),
				mysql_real_escape_string(md5($password)));
			$result = mysql_query($query);
			list($is_admin) = mysql_fetch_row($result);
			if($is_admin == 1) {
				header('Location:admin.php');			
			} else {
				header('Location:index.php');				
			}
		} else {	?&gt;
&lt;span style='color:red'&gt;Error: that username and password combination does not match any currently within our database.&lt;/span&gt;
&lt;?php	}
	}
?&gt;
&lt;form action='login.php' method='post'&gt;
Username: &lt;input type='text' name='username' /&gt;&lt;br /&gt;
Password: &lt;input type='password' name='password' /&gt;&lt;br /&gt;
&lt;input type='submit' value='Login' /&gt;
&lt;/form&gt;