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:

ALTER 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:

1
2
3
4
5
<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:

1
2
3
4
5
6
<?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):

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
		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():

2
3
	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:

15
16
17
18
19
		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:

18
19
20
21
22
23
			$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 {	?>
<span style='color:red'>Error: that username and password combination does not match any currently within our database.</span>

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:

22
23
24
25
26
27
28
29
30
31
32
			$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 {	?>

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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 {	?>
<span style='color:red'>Error: that username and password combination does not match any currently within our database.</span>
<?php	}
	}
?>
<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>

Wish there was more?

I'm considering writing an ebook - click here.

.

Luke is the primary editor of Building Browsergames, and has written a large portion of the articles that you read here. He generally has no idea what to say when asked to write about himself in the third person.

Thursday, April 24th, 2008 buildingbrowsergames, code, php
  • random person

    parse error:syntax error, unexpected T_string on line 10.

    $query = sprintf("SELECT COUNT(id) FROM users WHERE UPPER(username = UPPER('%s') AND password = '%s',

    what am I doing wrong?

    don't ask me to.paste the whole code. I'm using my.phone to look at this and then typing it on my computer.

  • Siem Wigger

    thanks so much, the part about the session was completely new to me and helped me a lot!

  • techomaniac

    great site! thanks!

  • Trxxy

    @Thomas

    Put the php code above HTML. and it will work. PHP.net's answer under...

    **************************
    <html>

  • Trixxy

    @Thomas

    Put all the PHP code above your HTML, try that. It worked for me ;)

  • santu

    thanks a lot...worked perfectly......

  • If it's telling you that the headers have already been sent, chances are that you've missed the } else { line inside the code. If you do that, PHP will try to output two headers right after each other, which won't work - have you missed a line in your code?

  • I've entered all of the code etc. but, it comes up with some errors when I try to run it:
    Warning: Cannot modify header information - headers already sent by (output started at /home/www/piegames.freehostia.com/PHP GAME/login.php:1) in /home/www/piegames.freehostia.com/PHP GAME/login.php on line 29

blog comments powered by Disqus

About

Building Browsergames is a blog about browsergames(also known as PBBG's). It's geared towards the beginner to intermediate developer who has an interest in building their own browsergame.

Sponsors

Got Something to Say?

Send an e-mail to luke@buildingbrowsergames.com, or get in touch through Twitter at http://twitter.com/bbrowsergames