If you’ve got more than one file – such as a script control panel – that you want protecting, my Secure Login Page is more hassle than is needed to get an adequate level of protection. Using a similiar no-database concept though, we can make use of sessions to help protect our files.
Firstly, we need to create our config file. This is where we’ll stick our usernames/passwords and a random ‘salt’ (I’ve started using things like hashed dates, which obviously change with time giving increased security). To enable us to have multiple logins, we can use an array to hold all the data as neatly as possible:
<?php
$users = array(
"username" => "password",
"another" => "theirpass"
);
$salt = substr(md5(date("F")), 8);
?>
For each new login add a new line in the format: "username" => "password", adding a comma to the previous line as a separator. This creates an array with the username as the key and password as the value. I highly recommend you hash the passwords using an MD5 hashing tool before putting them in the file. For example:
<?php
$users = array(
"username" => "5f4dcc3b5aa765d61d8327deb882cf99",
"another" => "85103ecee5a5e98c2923978385e514a2"
);
// this takes the month, hashes it then cuts it down to 8 characters
$salt = substr(md5(date("F")), 8);
?>
I will continue the tutorial assuming the passwords are hashed.
Once you’ve set this up, save the file as something like users.php and create a new file called login.php — in this we’ll put our login script. This will include the form, the initial session creation and storing of the username/password. For the sake of speed, I’ve coded the basics of an HTML form already (if you need this explaining to you, this tutorial is probably not for you):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Login Form</title>
</head>
<body>
<form method="post" action="login.php">
Username:<br>
<input type="text" name="username"><br>
Password:<br>
<input type="password" name="password"><br>
<input type="submit" name="submit" value="Login">
</form>
</body>
</html>
We’ll use this to gather our login details, and direct the user back to login.php (by which point we’ll have put in our magic PHP.) We can start by checking the request method of the page… if it’s POST (rather than GET) there’s a pretty good chance our potential user has filled out the form, so we can process the details. Validation of the data that we’ve received is a good start, so we’ll check for special characters in the username and hash the contents of the password ready for comparison:
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!ereg("^[A-Za-z0-9]", $_POST['username']))
exit("<p>Invalid characters in the username.</p>");
$username = $_POST['username'];
$password = md5($_POST['password']);
}
?>
At this point we’ve got our ‘clean’ username, and hashed password, assigned to relevant variables. Of course, just because the username doesn’t contain anything dodgy doesn’t mean it’s correct. Now we need to call our file with the usernames in (users.php) and check to see if the username and password are a valid combination. We can use array_key_exists() to check for the existance of our username (remember: our usernames are stored as keys) and if it’s there, we can check the value of the key (our password) against the submitted password:
require('users.php');
if (array_key_exists($username, $users)) {
// at this point we know the username exists
// let's compare the submitted password to value of the array key (the right password)
if ($password == $users[$username]) {
// password is correct
} else {
exit("<p>Invalid password.</p>");
}
} else {
exit("<p>Invalid username.</p>");
}
At this stage we know whether or not the password is correct, and can start working with our sessions. We need to call session_start(), and create a session variable that we’ll be checking later on each time a user tries to access a page. Once this is done we can redirect our user to a page of your choosing (generally one that is going to be protected by the script):
session_start();
$_SESSION['loggedin'] = md5($username.$password.$salt);
header("Location: your-page.php");
exit;
So, all together, our login script is as follows:
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!ereg("^[A-Za-z0-9]", $_POST['username']))
exit("<p>Invalid characters in the username.</p>");
$username = $_POST['username'];
$password = md5($_POST['password']);
require('users.php');
if (array_key_exists($username, $users)) {
// at this point we know the username exists
// let's compare the submitted password to value of the array key (the right password)
if ($password == $users[$username]) {
// password is correct
session_start();
$_SESSION['loggedin'] = md5($username.$password.$salt);
header("Location: your-page.php");
exit;
} else {
exit("<p>Invalid password.</p>");
}
} else {
exit("<p>Invalid username.</p>");
}
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Login Form</title>
</head>
<body>
<form method="post" action="login.php">
Username:<br>
<input type="text" name="username"><br>
Password:<br>
<input type="password" name="password"><br>
<input type="submit" name="submit" value="Login">
</form>
</body>
</html>
At this stage we now have the capacity to log a person in, but nothing protecting our actual files. We need to create another file — check.php — which will contain the important session checking which will need to be included at the top of any page that needs protecting. We’ll start by checking that the session variable we created on login exists:
<?php
session_start();
if (!isset($_SESSION['loggedin'])) {
header("Location: login.php");
exit;
} else {
// the session variable exists
}
?>
If the variable exists, we can check that it contains what it should. To refresh your memory: the variable should contain the username, hashed password and 8 character salt from users.php all hashed together. We’ll loop through our users array to find a username and password that matches the session variable and chuck them out if it doesn’t:
// the session variable exists, let's check it's valid:
require('users.php');
$userexists = false;
foreach($users as $username => $password) {
if (md5($username.$password.$salt) == $_SESSION['loggedin'])
$userexists = true;
}
if ($userexists !== true) {
exit('<p>Invalid session: please <a href="login.php">login</a>.</p>');
}
Put it together:
<?php
session_start();
if (!isset($_SESSION['loggedin'])) {
header("Location: login.php");
exit;
} else {
// the session variable exists, let's check it's valid:
require('users.php');
$userexists = false;
foreach($users as $username => $password) {
if (md5($username.$password.$salt) == $_SESSION['loggedin'])
$userexists = true;
}
if ($userexists !== true) {
exit('<p>Invalid session: please <a href="login.php">login</a>.</p>');
}
}
?>
This can now be included at the top of any file that needs protecting (before any other HTML/PHP content), and it will force any user who’s not logged in properly to “exit()“. Here’s an example page with the check.php file included:
<?php require('check.php'); ?>
<p>If you can see this you're logged in :3</p>
That’s it – we’re done. Add and remove users as necessary (don’t forget to hash those passwords), and protect as many files as you want.



This is awesome. Thank you. I have got this working and it will do just what I wanted I think. Is there a way to store the destination URL the user was trying to reach so that you can deliver them there once the login sequence is done?
Hi,
Just thought I’d let you know that the link to the hashing tool leads to an error page.
edit ‘login.php’ file… find ‘your-page.php’ option….. replace it with the php or html file you want…. if the php or html file is not in the same directory, then mention the full path.
hope, that helps.
This is exactly what I need…will be pinching the code. Ta very much.
Do you know how can I protect a private key (to decrypt database content) stored in a session variable?
See, my problem is I’m using asymetric encryption. The private key to read de data is safely stored in the user database symetrically encrypted with AES under the user’s password.
So when the user wants to read something he just logs in and gets the private key with his pass, stored under a php session var for further use.
Anybody who has access to this session var can retrieve the private key and steal al the cyphered content from the database file.
Any ideas?
Anybody who has access to this session var can retrieve the private key and steal al the cyphered content from the database file….
Anybody who can hijack the session, can access session var…
Anybody who can perform a MIM (or MITM) attack, can hijack the session…
My recommendation is, use https with a strong (as strong as 128 bit or 256 bit) SSL encryption, instead of general http.
How about a logout function?
I dont even know if thats needed from a technical point of view, but it would certainly add to design :)
You could just clear the session or use to log out.
Hi, one thing I always wondering about is the question, how I can let the user set up his own password. and how I can protect the input form
”
Username:
Password:
”
from sending the unhashed password via the web to the server.
Do I have to hash it via javacript before sending it or du I have to use a https connection with a certificate to provide a secure password transmission?
Does anybody know an answer to this?
Greetings and thanks in advance!
Uwe
I’ll always prefer the idea of using a https secure connection. If you have a secure connection (SSL Certificate is what you need), then you don’t need to hash the passwords anymore. Because the SSL encryption does the hashing job. If you’re not using a https, then you can do the hashing part yourself.
This is a highly recommended tutorial for the beginners.
Hi dear,
Its very helpful note for an PHP regular user person.
If it is more essay how to one normal person can know it and identified
this.
Please can you help me to give php code for multiple user log in code.
Where one user can log in one page like a gmail, ymail, account.
I am a Student in DCS.
I find this post very helpful. But I can’t seem to figure out how to customize the username and password. When I change it in the script it doesn’t word. The log in function only works when the username is set to ‘username’ and password set to ‘password’
Greetings and thanks in advance!
/ Oskar
I keep getting “Invalid username”. How or where do I set the username?? I’m setting it in the users.php page now but again doesn’t seem to work.
Doesn’t work with php5.3 :(
I’ve not had any problems with this under php5 – can you shoot me a mail with what errors/problems you’re having? jem@jemjabella.co.uk
This is the second time in a row that i found exactly what i needed at your site.. this works perfectly….
If anyone is having trouble – make sure to HASH your passwords in your users.php since the code is -decrypting them during login process..