[Tutorial] Basic Admin Portal in PHP

Ghost

Seasoned Veteran
Blogger
Jun 25, 2009
3,198
185
213
Earth
wubur.com
FP$
2,483
Hello everyone! Today I will be sharing a super simple tutorial on how to create an administrator or user dashboard with a login page & logout function. This can be used for anything, but today we will only be focusing on the permission system to keep you logged in. It won't be the most secure or advanced dashboard because the point of this tutorial is to help beginners create their very first dashboard from scratch. Of course, everything in this tutorial can be expanded upon to make the dashboard more enhanced, such as with a database instead of a file-based system and checking details such as IP address, browser/user agent information, and more to ensure the logged in user is who they say they are. I originally posted this on CodeForum, a community owned by Malcolm who is a member here at FP. I wanted to share this tutorial here as well so more people can benefit, but you can see my original post here: https://codeforum.org/threads/create-secure-php-dashboard-from-scratch-tutorial.291/?view=date#post-1492

Before we begin I would like to go over the finished project file structure...
  • index.php
  • dashboard.php
  • config.php
  • controllers/
Inside the controllers folder:
  • login.php
  • logout.php


First things first, we are going to create a configuration file called config.php in the main project directory
I have set up a mini project folder called nodb-dashboard/, so it's mysite.com/nodb-dashboard/config.php
The path will be different for you, but we will be using relative paths the entire time so your project folder & site domain name will not matter at all.

For this file, I decided to use PHP definitions with the define() function so I can use the variables as system definitions throughout the scripts.
PHP:
<?php
define("USERNAME", "Ghost");
define("PASSWORD", "passy");
define("DASHBOARD", "GhostDash");
define("DESCRIPTION", "A super simple dashboard PHP tutorial by Ghost / William Passmore of Wubur LLC");
?>
In this code you can see that I define USERNAME and PASSWORD.
Although this is not very secure because it's not hashed, it will work for our tutorial.
In reality, we should be storing a password_hash( ) or another hashed string in the config.php file & rehashing after login to see if it's correct. This protects you against any attack in which the hacker gains access to your files. However, I want to get the ball rolling, so we'll just stick with plaintext for now.

I also define DASHBOARD and DESCRIPTION so I can echo these out throughout the system if I wish to without having to change a ton of pages if I decide to change the dashboard's name (GhostDash).

The PHP define() function works like this in our case... define(VARIABLE-NAME, VALUE). The value does not have to be a string. For example... define("booleanLowercase", true); which assigns the non-string true.

Now let's create our simple HTML login page, which will be on index.php
PHP:
<?php require_once "config.php"; ?>
<html>
    <title><?php echo DASHBOARD ?> Login</title>

<h2><?php echo DASHBOARD ?> Login</h2>
<form method="post" action="controllers/login.php">
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">Login</buton>
</form>

</html>
We start off by using require_once "config.php" to make sure that our configuration settings are available to this script. Because config.php is inside the same folder as index.php, we do not need anything in front of config.php in our filepath.
We then set up some very basic HTML with the <title> tags!
As you can see, we start up PHP again by using <?php echo DASHBOARD ?>

This takes the defined DASHBOARD variable from our config.php file, so it will correctly echo out 'GhostDash', to say GhostDash Login!
I do this again in some basic header <h2> tags below, before creating the form.

Inside the form, we just have a very basic setup with HTML.
We use the method="" to declare we are using POST, and action="" to target our actual login controller file.
As you can see, there is a path in the action="" because our actual login.php file is inside our controllers/ folder
Then we just set up the input text field for username, and password input as well. With a primitive submit button, we are good to go!


Now let's move over to our controllers/ folder and pull up our login.php file
PHP:
<?php
require_once "../config.php";
if(isset($_POST['username']) && isset($_POST['password'])){
    if(strtolower($_POST['username']) == strtolower(USERNAME) && $_POST['password'] == PASSWORD){
        session_start();
        $_SESSION['loggedin'] = true;
        $_SESSION['username'] = USERNAME;
        header("Location: ../dashboard.php");
        echo "Redirecting to <a href='../dashboard.php'>secure {DASHBOARD} homepage</a>"; // in case redirect fails, they can click link
    } else {
        header("Location: ../index.php");
        die("The account details supplied are incorrect.");
    }
} else {
    header("Location: ../index.php");
    die("Username and password must be supplied to log in.");
}
?>
Once again, we start by including our config.php file at the top, but this time we use ../ in the path to let the server know that the file is located one directory "up". This is because our config.php file is not inside the controllers/ folder, it's in the project folder that controllers itself resides in.

Then we use a general isset() function to see if the $_POST variables are set.
We look for $_POST['username'] and $_POST['password'] because those are the names of our inputs on the HTML form for our login.
If they are not set, we redirect them back to ../index.php , our main login file. We also have a redundant die("error msg"); function after each header location redirect just in case the redirect fails. This prevents them from accessing any part of the script if a failure is detected.

In the next segment of code, once we know that password & username POST variables are indeed set, we compare them to our defined values from config!
So, we say if $_POST['username'] == USERNAME, and do the same for PASSWORD.
You will notice that the username is also using a PHP default function called strtolower()
We use this so that you can type in the username however you wish & it will work as long as the username is the same in the config file. I personally like doing this so that if I ever make a dashboard with multiple users, there can't be one user called Ghost and another called ghosT.

If the values are the same for username & password, we need to "start our PHP session" with session_start();
This allows the server to know we want to access $_SESSION variables, which are basically like secure cookies that are only set by the server. These *can* be "hijacked" by hackers, but for this tutorial we will not be jumping in to prevention methods for that due to its complexity and the amount of writing required to explain it all... It also becomes increasingly more important to use a database for data integrity & management when you are making an even more secure dashboard. So our no-DB file based system will stay simple! :)

We start by setting $_SESSION['loggedin'] equal to true, and then we create $_SESSION['username'] so we can echo out it.
You may be wondering why we do this because the username is stored in config.php - I wanted to show you that you can indeed set some strings for the session variables because loggedin is set to a boolean (true)

Then we redirect to dashboard.php & echo out a simple message just in case the redirect fails!

dashboard.php is our secure page for this tutorial!
PHP:
<?php
require_once "config.php";
session_start();
if(!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] != true || !isset($_SESSION['username']) || $_SESSION['username'] != USERNAME){
    header("Location: index.php");
    die("Access Denied");
}
?>
<strong><?php echo DASHBOARD ?></strong> | <?php echo DESCRIPTION ?> | <a href="controllers/logout.php">Logout</a>
<hr>
This is secure content that only the logged in administrator can see.
We start off by using session_start() again! Remember, we must use this before we can set or view / analyze any $_SESSION variable! It's very important.
We then look to see if our sessions are set properly. We first use !isset($_SESSION['loggedin'], which basically says "if loggedin session variable is NOT set" because of the !exclamation point! before isset. We then check to see if the variable is not set to true. If either of those is not set properly, it will trigger the code that redirects back to index.php / uses die("Access Denied").
Additionally, our if statement also uses !isset() for our username & even checks to make sure it equals our config's username value. Again, if either are not correct it will redirect back to index.php - our login page.

Assuming everything is okay, the code block ends & we start showing our secure data.
Ideally the logged in checker would be in a separate file that we could include on multiple secure pages, so that we do not have to manage multiple logged in checks across many scripts.
We would throw this in a file like "login-check.php" and require that file in each page we want to be secure.

Our secure HTML / page is very simple... We echo out our dashboard name & description, and then throw up a link to our logout controller.
Below that I just have a simple message demonstrating that the page is secure. If you try to visit dashboard.php without logging in, you will never see that content & will be redirected!

So... Let's wrap it all up with a logout controller. This is definitely important because you do not want to log in on someone's computer and leave your dashboard exposed.

controllers/logout.php:
PHP:
<?php
session_start();
session_destroy();
header("Location: ../index.php");
echo "Redirecting to <a href='../login.php'>{DASHBOARD} Login</a>"; // in case redirect fails, they can click link
?>
Once again, we will need to use session_start();
Even though we are not setting any session variables or checking their values, we will be destroying the session and that means we must start it up.
It may sound odd, but when you use session_start() it doesn't mean you are actually starting a new session... It means you are telling the server to start accessing the session functions, whether it's actively in use or not.

We then immediately use session_destroy() which removes/destroys all the session variables & ensures the user is logged out fully.
Then we immediately redirect the user to the index.php / login page & also show a short message telling them of this in case there are any issues.

99 times out of 100 those header location redirects will work, but I do like to include messages and redundant die() or exit; so that the script has a fallback in case of any possible failure. There are times for example when another page (especially included/required files) has code in it that will prevent a header location from working, so sometimes I will even go as far as echoing out a JavaScript redirect as well for maximum redundancy. 99 times out of 100 any possible failure is due to a developer including or altering a file in a way that breaks header("Location...

-----
That's it! You have now learned everything required to build a super simple single-sign-on dashboard with PHP & no database required.
It's very simple and to be honest, it took me longer to explain the code than it took me to write it. You can write this up in mere minutes if you know what you are doing, but for you beginners out there I highly recommend you play around with everything, try to break your dashboard, and expand upon it!

If you want to download GhostDash tutorial code, you can do so with any of these links:
https://www.mediafire.com/file/dv5bsnc761tp5c5/GhostDash.zip/file
 

Ghost

Seasoned Veteran
Blogger
Jun 25, 2009
3,198
185
213
Earth
wubur.com
FP$
2,483
Very helpful to those that are new or starting out. For me it's like an refreshment reading
Thanks for checking it out Empire :)
I agree, it will come across as incredibly basic for more experienced programmers, but hopefully can help some people starting out. I am going to push it to GitHub so that it's a bit more accessible, but this is really intended as an introduction to sessions & private pages. Ideally a beginner programmer will already know a lot of the functions & code in use here, but just needs some guidance... Then they can enhance the dashboard by incorporating a database, more security features, and adding some actual content into the dashboard!