Building a user authorization system in PHP - part I
Recently I needed to start my new PHP project and required a basic (but secure) user authorization / registration script. To my surprise I was not able to find one script that would allow me to register users in MySQL database, require user activation via email, show a turing (aka captcha) at the login form and have no obvious security holes.
16 hours later, I now have my own script and understand better why there is no universal script available on the Net (the task turns out non-trivial and requires a lot of security tweaking).
In this post I will start discussing how a user authorization script should be developed. You will be interested in this script if you:
1. Create projects in PHP
2. Require some basic user registration and login
3. Do not want your site to be easily hackable
Ok, here goes…
Any basic user auth script will consist of the following:
1. Registration HTML form
2. Registration validation
3. Creating a user record in MySQL
4. Login HTML form
5. Login validation
6. Session creation and management
7. Session destruction on logout
Apart from these it is also always nice to have the following:
1. Use a captcha to prevent automatic registrations
2. Store a list of crack attempts and ban users
3. Encrypt password
4. Send activation emails
5. Prevent MySQL “insertion bug” attacks
6. Prevent session hijacking
1. Creating an HTML registration form
So, let’s start with the easy part: the HTML form. Here it is. Copy & save it to a file called form.php (there is no php at the moment, only pure HTML but you might need it later).
<!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″ />
<title>Registration form</title>
</head>
<body>
<form id=”registrationform” name=”registrationform” method=”post” action=”register.php”>
<input type=”hidden” name=”regform” value=”regform” />
<label>Username: <input type=”text” name=”username” maxlength=”15″/> </label>
<label><br /> Email: <input type=”text” name=”email” maxlength=”40″/> </label>
<label><br /> Password: <input type=”password” name=”password” maxlength=”20″/> </label>
<label><br /> Verify password: <input name=”password2″ type=”password” maxlength=”20″/> </label>
<br/> <input name=”submit” value=”submit” type=”submit” />
</form>
</body>
</html>
Here are some comments: This is how the HTML FORM is set up:
<form id=”registrationform” name=”registrationform” method=”post” action=”register.php”>
Method should always be POST, which is a tiny bit more secure. The script name in action attribute is “register.php”, we will call this script once the user hits “Submit” button.
After that follows the standard input forms for your registration form. Spend some time thinking what information you will require on your site users.
<input type=”text” name=”username” maxlength=”15″/>
The only things to note here is that the name attribute should be unique (you will need it later) and every field should have a maxlength, so that user will not be allowed to enter a 250-letter long username.
Finally, this code actually displays a button and submits the form to our script “register.php” if you click on it or hit “Enter”:
<input name=”submit” value=”submit” type=”submit” />
2. Creating a MySQL table to hold users
Ok, now you need somewhere to store all this info. You should already have a MySQL database ready (you should know username, database name, database password and database address). The usual set-up for hosting providers is to give you a username = database name = your login at hosters and database address is most of the time “localhost”.
You should also have some way to administer the MySQL. Usually it’s phpMyadmin. Go there, select the database and click SQL. Paste the following code in the dialog and execute it (but before doing that, better read what it means below!)
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(15) NOT NULL default ”,
`password` varchar(100) NOT NULL default ”,
`ip` varchar(20) NOT NULL default ”,
`email` varchar(50) NOT NULL default ”,
`status` int(3) NOT NULL default ‘0′,
`added` timestamp NOT NULL default ‘0000-00-00 00:00:00′,
PRIMARY KEY (`id`) )
ENGINE=MyISAM DEFAULT CHARSET= latin1 AUTO_INCREMENT;
SQL actually has a very simple syntax. We are creating a table “users” which has 7 fields. id is the id of the record, every record should have one, and it should be unique. You let MySQL select the id for you by specifying “auto_increment”. There are 3 most useful data types (at least for the registration form) in MySQL: INT, VARCHAR and TIMESTAMP.
You use INT to store integers, you use VARCHAR to store strings and you use TIMESTAMP to store date and time. We should also specify length for INT and VAR in round brackets. If you need to add more fields to the table, it can easily be done using phpMyadmin (see its documentation).
Once the table is created, it is time to create our register.php script, that will receive the values from the application form.
3. Creating the register.php script
First, define those variables, filling in the appropriate info:
$db_host=”localhost”;
$db=”yourinfohere”;
$db_user=”yourinfohere”;
$db_passwd=”yourpasswordhere”;
Then, create the procedure to connect to the database:
function db_connect() {
Global $db, $db_base, $db_user, $db_passwd;
$connect=@mysql_connect($db_host,$db_user,$db_passwd);
if(!$connect) return $connect;
$connect=@mysql_select_db($db);
return $connect; }
Now, call the function and it should connect to the database. You can test it by writing something like:
If (!db_connect()) { echo “Error connecting!”; }
Ok, to make you happy, let’s create a user based on the info you sent in the HTML form. Here is the code you will use:
$ip = $REMOTE_ADDR; // this will get user’s IP address
$username = $_POST[“username”];
$password = $_POST[“password”];
$email = $_POST[“email”];
$query = “insert into users set
ip=’$ip’,
username=’$username’,
password=’$password’,
egold=’$egold’,
email=’$email’,
added=now(),
status=’0′;”;$res=@mysql_query($query);
Some explanations here: the fields enters into the application form are being passed in the $_POST array to your script. The identifier of the array item is the name of the INPUT tag.
So, if you want to extend your registration form to include an address, for example, you will need to add the following:
To your form.php:
<label><br /> Address: <input type=”text” name=”address” maxlength=”60″/> </label>
To your database creation script:
`address` varchar(60) NOT NULL default ”,
To your register.php:
$address = $_POST[“address”];
And finally you need to modify the SQL query to look like this:
$query = “insert into users set ip=’$ip’,
username=’$username’,
address=’$address’,
password=’$password’,
egold=’$egold’,
email=’$email’,
added=now(),
status=’0′;”;
Hopefully, you will find it simple. It really is
4. How it all gels together
Now, let’s see how it works. You should have a MySQL table “users” and two files – form.php and register.php. Upload it to your hoster and run the form.php file. Fill it out and click “Submit”. Now, the register.php file should be loaded in your browser and it will show an empty page.
However, if you go and take a look at your MySQL table “users”, a new record will be created there with the details you provided. This is basic stuff, but you are on the right track.
Just a quick note on this - it’s good practice to store the password encrypted in the database. Although this makes it a pain if the user forgets their password (you can’t do the insecure option of mailing them their exisitng password) it does mean - if you use MD5 encryption - that the password column will be 32 characters long every time!
Posted 1 year, 12 months agoOne other, far more serious problem: the above is right open for a SQL injection attack. I just got hit by this in a script I wrote 6 years ago when I didn’t know any better.
Basically, whenever you insert values into the database that come from user input, you must escape them, so people cannot enter malicious data to alter your SQL query.
To prevent this happening, you want to call mysql_real_escape_string() for each of the values in your query. Have a look at that manual page, it gives some good overviews.
Good luck with your future programming! There’s no ’subscribe to comment updates by email’ feature here, so please notify me by email if you reply.
Posted 1 year, 12 months agoAlso, you are inserting the variable “egold” into the tableset, which isn’t defined anywhere, which I am assuming is part of your personal version of this form. It’s really just taking up space, here
Phil
Posted 1 year, 10 months agoAdministrare Server
Posted 1 year, 6 months agofsdfsdf
Posted 1 year, 5 months agoPosted 1 year, 4 months ago
this is bullshit, and never use ” instead of ‘ or ” ….
Posted 1 year, 2 months agoHey LOL don´t insult here.
Posted 1 year, 1 month agoHello
Very interesting information! Thanks!
Bye
Posted 11 months, 1 week agothey’ll have you suicidal suicida. Liana Merete.
Posted 11 months, 1 week agosee it’s very define,your one of a kin. Liesbeth Kiki.
Posted 10 months agowhere is the other stuff?? i really wants to know how to control the permission, how to prepare the db for user role and permission will somebody will help me??
Posted 7 months, 2 weeks ago- - (, , )
Posted 4 months, 1 week ago?