Creating Your Own CMS With Secure Login

Creating Your Own CMS Part 1 – Secure Login

Have you ever built a site to realize it is a pain to manage? There are a lot of CMS options out there but some of them cost money, some are hard to learn, some your hosting company might not support, and well sometimes they just don’t have everything thing that you want. So today I am going to start to teach you how to create your own simple CMS. Today I will get into how you can find a design and get your secure login setup. This will be a series of blogs but to be honest I am not sure how advanced I will be going. If I wanted to spill it all and tell you how to build the CMS that my company uses then it might take a few blogs.

preview creating cms secure login design tutorials

Design of Your Own CMS

This may or may not be important to you. But when it comes down to it you will most likely be much more proud of your CMS with a nice design and design is where the usability starts. I could programming some amazing things but without a design I am limiting myself and wasting a lot of time. I have created a few CMS’s from scratch but I found out that when you give me a design for a CMS it not only comes out a lot neater but I can produce it much faster.

Here is the one that I chose as well as a few others to browse through.

I am creating this CMS as I type this so you guys are looking at it first hand. That is also the main reason I am not sure how many advanced parts we will have but I am willing to take requests while I work.

A Few Things To Have Before You Begin the Login

If you haven’t already setup the database then you can refer to one of my recent posts “Getting Started With MySQL DB and PHP with PHPMyAdmin”. Along with the database it is nice to have a database class file and a database connection file. These are two files that you will be using on each project you do so it is nice to have them on hand. The db.php can just go in the htdocs/ and the db.class.php should go in the htdocs/classes/ folder.

People do their file structure differently but for me I have an Ubuntu server with each site in the home folder like: /home/
Within the htdocs/ we will want a few different folders as well.

  • admin/
    • classes/
    • css/
    • images/
    • includes/
    • lib/
    • markitup/
  • cache/
  • classes/
  • css/
  • images/
  • includes/
  • lib/

Most of this layout is pretty self-explanatory. You would have your index and other content files in the htdocs/ and in the htdocs/admin/ would be all of you admin content. Then the rest of the folders are all labeled for exactly what should be going in them. The cache/ folder can be used for several different items depending on the type of website that we are building.

Obviously this is not required nor any sort of standard this is just how I like to layout my sites file system to try to keep things neat.
Here the folder “markitup” contains a jquery markup editor which I actually haven’t used until now. I usually use ckeditor for a full featured easy to use editor.

Secure Login Code

With a secure login we will want to use sessions. You can get into more advanced parts with heavier use in cookies also but for now I am just going to show you a very basic secure login with a timeout on it. First though we need to make sure that when people try to go anywhere on our site that they will get sent to the login if they are not already logged in. Se we should put this in the header.php because that is included on every page in the admin, and we can do it like this.

1 <!--?php         if(!$_SESSION['llafl_admin'])         {         $_SESSION['REQUEST_URI'] = $_SERVER['REQUEST_URI']; //store the page they were trying to access         header('Location: /admin/login.php');       exit;   } ?-->

You can see here I am checking for a session variable which I have named ‘llafl_admin’. It is best to have a distinct session because if not then you run the chance of some other site having the same session variable. Like if we just made the variable ‘admin’, it is so generic it could be anywhere. So since we have a check like this that means that when someone is logged in then they should have a session variable ‘llafl_admin’, which we will do like this.

1 <!--?php <br ?-->  if($_SESSION['failed']=='yes')
2         echo '</pre>
3 <div id="fail" class="info_div"><span class="ico_cancel">Incorrect username or password!</span></div>
4 <pre>
5 '; // display failed login if need be
6 ?></pre>
7 <form id="loginform" action="/admin/login.php/" method="post" name="loginform"><label><strong>Username</strong></label><input id="user_login" class="input" type="text" name="username" size="28" />
9  <label><strong>Password</strong></label><input id="user_pass" class="input" type="password" name="password" size="28" />
11  <strong>Remember Me</strong><input id="remember" class="input noborder" type="checkbox" name="remember" />
13  <input id="save" class="submit" type="submit" value="Log In" /></form>
14 <pre>

That is a a basic login form and below is the code to handle when it is submitted.

1 <!--?php     if($_POST)  {       if(!$_POST['username'] || !$_POST['password'])          $_SESSION['failed']='yes';      else        {           $username = stripslashes($_POST['username']);           $password = md5($_POST['password']);            $u_q = $db--->query("SELECT * FROM users WHERE username='$username' AND password='$password' LIMIT 1");
2             $u = $db->fetch_assoc($u_q);
3             if($u['id'])
4             {
5                 $_SESSION['llafl_admin'] = $u['access_level'];
6                 $_SESSION['started'] = time();
7                 foreach($u as $key => $value)
8                     $_SESSION[$key] = stripslashes($value);
9                 $last_login = date('c',time());
10                 $db->query("UPDATE users SET last_login='$last_login' WHERE id='".$_SESSION['id']."' LIMIT 1");  // on successful login update users last login
11                 header('Location: '.$_SESSION['REQUEST_URI']); //if they successfully log in then send them to the url they requested which is something I have set in the header
12                 exit;
13             }
14             else
15                 $_SESSION['failed']='yes'; // if they failed to login this will set a session var that will trigger an error message
16         }
17     }
18 ?>

You can see here this script checks to make sure that both inputs were indeed submitted and if they were then it goes on to check to see if they are in fact part of a legit login. Then if it is successful then the appropriate session variable are set. (You notice we do a stripslashes to sanitize the username and md5 will sanitize the password and make sure that it is not stored human readable in case the database were to be compromised.) And if not then a session variable for ‘failed’ will be set and when the login form reloads it will trigger an error message. There are many more security levels that you can add onto this but this is a very basic and secure login that will work for our purposes.

If you are confused by any of the database aspects then refer back to this post.

Creating Your Own CMS Part 2 – Access Levels & Administrators

Alright if you have read the first article that we worked on a while ago “Creating Your Own CMS Part 1 – Secure Login” then you should have some sort of CMS design with a secure login. Now that we can login to our CMS we will need to have an easy way to add an administrator and of course give them access to only certain parts of the CMS. But first one little thing that I decided to add in to make it easy for you to login without having to manually add an entry in phpmyadmin was to make the first login attempt double as a create user.

preview larg admins tutorials php css coding tutorials css

1 <?php
2         //this first part checks to see if you are already logged in and if you are it redirects you
3         if(isset($_SESSION['started']))
4     {
5         header('Location: /admin/');
6         exit;
7     }
9         //this next is actually something that i just thought of because it is annoying to
10         //have to add an entry via phpmyadmin with a md5  password (and even worse
11         //when you get into much more secure passwords)
12         if(isset($_SESSION['failed']))
13         unset($_SESSION['failed']);
14     if(isset($_SESSION['no_su']))
15         unset($_SESSION['no_su']);
16         //above clears out the no_su and failed session variables to clear just in case
18     $su_check = $db->query("SELECT id FROM logins WHERE super_user='1' LIMIT 1");
19     if(!$db->num_rows($su_check))
20         $_SESSION['no_su']=true;
21         if($_POST && !$_SESSION['no_su'])
22     {
23         //here is the login code that we used before
24     }
25     elseif($_POST && $_SESSION['no_su']==true)
26     {
27         //no_su is only set if there are no entries in the logins table
28         //so this will put one in there
29         $username = stripslashes($_POST['username']);
30         $password = md5($_POST['password']);
32         $db->query("INSERT INTO logins (username,password,date_added,super_user) VALUES('$username','$password','".time()."','1')");
33         unset($_SESSION['no_su']);
34     }
35 ?>

You can see in the above query that I set the field super_user=’1′ on my insert. I did this because this should be the main/root/admin account or whatever you would like to call it. And later when we make permissions the super_user will be giving access regardless.

I do also add a little note when the login page loads so that you know you are not trying to login but you are actually setting up the main/first login account. This is accomplished by adding a block of php in the html that creates the login box like below.

1 <?php
2     if(isset($_SESSION['failed']) && $_SESSION['failed']=='yes')
3         echo '<div id="fail"><span>Incorrect username or password!</span></div>';
4     elseif(isset($_SESSION['no_su']) && $_SESSION['no_su']==true)
5         echo '<div id="fail"><span>SETUP SUPER USER ACCOUNT!</span></div>';
6 ?>

As you can see above, there is also a check for a failed attempt that will output an error message if need be.

Adding And Editing Access Levels

Access levels are something that can vary greatly depending on the site and it’s requirements. A site could be managed by one person and need only one level, that being total access. Some sites will hire freelance blog writers, and these writers do not need access to anything more than the most basic levels which allow them to write and save their posts. I mean seriously, there are some real nut cases out there, just because you think you know someone doesn’t mean you should let them have access to your site. The access level control that we are going to create is pretty powerful, and very flexible, but will not be as in depth as something bigger sites would have.

The logic behind the access levels that we are going to use is going to be as simple as giving certain people access to certain php files. We can also have a setting to give them access to live content or not. First, to make it easy to keep track of the files that we want to restrict access to we are going to create an array of the “admin pages”. The beauty part of this array is it can be used for more than just access levels. We will use this array to actually build the site navigation and to restrict access. Obviously there are other ways to do this, but if we have it all in an array then when we want to add a new page to our admin we will not have to change any coding to add it to the access levels and everything else.

1 <?php
2     $_AP = array(
3         array(title=>'Dashboard',
4             url=>'/admin/content/'
5             ),
6         array(title=>'Content',
7             url=>'/admin/content/content.php',
8             dd=>array(
9                 array(title=>'Add Content',
10                     url=>'/admin/content/content.php?action=add'
11                     )
12                 )
13             ),
14         array(title=>'Events',
15             url=>'/admin/content/events.php',
16             dd=>array(
17                 array(title=>'Add Event',
18                     url=>'/admin/content/events.php?action=add'
19                     )
20                 )
21             ),
22         array(title=>'Venues',
23             url=>'/admin/content/venues.php',
24             dd=>array(
25                 array(title=>'Add Venue',
26                     url=>'/admin/content/venues.php?action=add'
27                     )
28                 )
29             )
30         );
31 ?>

llafl admin2 tutorials php css coding tutorials css

You can see from the array I am building my navigation. So this way, when I want to add a new page to my admin I simply start by adding a new entry to the array. When I do this it will automatically be on the page. If I have key ‘dd’ with an array nested inside of there, it becomes a drop down. There are many different ways that you could possibly structure the array, and many different things that you can add to it. Below is the code that we use to go through the array and create that navigation.

1 <?php
2             function create_nav($ap,$close=false)
3     {
4         define('LB',chr(10));
5         $output;
6         if(is_array($ap))
7         {
8             $count = count($ap);
9             $i=1;
10             foreach($ap as $k => $v)
11             {
12                 $output .= '<li><a href="'.$v['url'].'">'.$v['title'].'</a>'.LB;
13                 if($v['dd'])
14                 {
15                     $output .= '<ul>'.LB;
16                     $output .= create_nav($v['dd'],true);
17                 }
19                 if($close==true && $i==$count)
20                     $output .= '</ul>'.LB;
21                 $output .= '</li>';
22                 $i++;
23             }
24         }
25         return $output;
26     }
28         //The function is simply called like this with $_AP obviously being the array of pages
29         echo create_nav($_AP);
30 ?>

You can see that this is pretty simple, it just runs through the loop and creates an unordered list of all of the items.

Now let’s build a simple form to add and edit users and access levels

I am going to assume that you know how to build form elements (and if you don’t there are some great simple tutorials right here on 1WD). So I am going to go through the logic behind it. You will of course want a simple for to add/edit users and a form to add/edit different access levels. First, lets talk about the access levels. For the access levels we can make it as simple as a form to name the access level and an array of checkboxes, one for each page. Then say I want to create an access level “admin” I would just type “admin” into the name textbox and check all of the checkboxes which will grant them access to every tab, as you can see below.

Access Levels

Then with the add/edit administrators you will simply want to hit up the database for all of the available access levels and put them in a drop down to choose from. And lastly I will show you how to put these to use.

When someone logs into the admin we set several session variables, and the users access level will be one of them. So we can just write a function that we put in the header, to make sure that it is on every page, that will check whether that person has access to the page they are trying to access. The function could look something like this.

1 <?php
2         function check_access(){
3             GLOBAL $db;
4             $al = $_SESSION['access_level'];
5             $a_q = $db->query("SELECT pages FROM access_levels WHERE id='$al' LIMIT 1");
6             $a = $db->fetch_assoc($a_q);//pages is just a serialized array in the database
7             $allowed_pages = unserialize($a['pages']);
8             $parts = explode('/',$_SERVER['REQUEST_URI'];
9             $count = count($parts);
10             if(!in_array($parts[$count-1],$allowed_pages)){ //if the page they want isn't in the array of pages they can have
11                 header('Location: /admin/');//send them home
12                 exit;
13             }
14         }
15 ?>

And here we have a very simple version of admins and access levels that is based off of php scripts access. We can take this further in many different ways, and one would be to also allow setting “action” access per page. Like allowing users to add/edit, but not delete. And it would be very simple to implement in the function that we just coded by checking the query string for actions.

Creating Your Own CMS Part 3 – Advanced Features

If you have been following along you should have a simple CMS built that has a place to securely log in and you should be able to create some users and access levels for your site. If you are creating a CMS you will need more than just to be able to log in and create users so here in part three we will get into a few of the things that you can do with your own CMS. A few people have really knocked the idea of creating your own CMS which is fine because we can all have our own opinions so I will just tell you all why I personally like to use my own.


preview large cm3 tutorials css php css css

Reasons You Might Build Your Own CMS

First off, the main reason is that you have 100% control. Yes, it can be a lot of work, but if you plan to have multiple sites then it is awesome to have your own CMS that you can easily fully customize to whatever you want. Secondly, I did this to further sharpen my PHP, JS, AJAX, Jquery, CSS, and HTML skills. The company that I work for does not, and will not, ever use open source CMS or even a retail CMS. There are several ups and downs to using a common CMS. The ups are that you can easily find people to help you work on things with it and one of the main downsides is if there is any sort of flaw or security issue then everyone will know about it quickly and you can be vulnerable to attacks until it is fixed.

Adding Content To Your CMS

To kick this off I would like to talk about the front end structure of your site first. If you want to be able to easily add content on the fly to your site then the layout has to allow for it. Unless you create a CMS that builds the entire page’s HTML files. The example that I plan to show you does not show building entire HTML pages, but it can easily be altered to do so. The basic setup of the content manager that I am showing you guys is going to require a layout that is flexible but simple and a little bit of work from the .htaccess.

The Back End For Adding Content

The actual back end itself is very basic but depending on your site and features it can very well be more complex if you like. You simply start with a form in your CMS to add/edit/delete content pages. This form will need at the very least a place for a url and a place to add content. Technically you do not need the url you could simply do a ?id=84 with the 84 just being an auto increment from the database. Obviously this is a pretty ugly way to do it so we will assign URLs to each. Along with a URL and content I always have at least a page title, meta keywords, and meta description but regardless of what you have it is all basically the same.

What You Need On The Front End

If you have made it this far along in the tutorials I assume you probably do not need any help with how to make this form so I will skip those details. However, I will just mention that each of the new content pages that you add with this form will need to be stored in a database. I do it with an auto increment id field for the PRIMARY key and also add an INDEX on the url field because we will be using that field to look up pages. From there you can handle the front end in a few different ways. You can go back to my flat file caching and cache out each content page as an array using the url as the key for each element so that it is easy to reference. I have done things like this in the past but don’t usually anymore as the benefits are really more opinion/preference than performance in many situations. Another option, and the one I most commonly use, would be to simply take the url and look up the page in the database then display the content. When done this way I like to have a header.php, header.init.php, and of course my index.php and footer.php. The header.init will be where I have the code to parse out the URL and try to find the content page in the database. The header is mainly just some html that contains the header area of my website and the index is the middle content area of my site that will display content per the given URL. You will also have a .htaccess file to handle redirects.


1 <br />
2 RewriteEngine On</p>
3 <p>RewriteCond %{HTTP_HOST} ^$ [NC]<br />
4 RewriteRule ^(.*)$$1 [R=301,L]<br />
5 RewriteCond %{HTTP_HOST} ^([www\.]?)$ [NC]<br />
6 RewriteRule ^(.*)$$1 [R=301,L]</p>
7 <p>RewriteRule ^tmp(.*)$ /admin/tmp_image.php [NC,L]<br />
8 RewriteRule ^(.*)(\.(jpg|jpeg|gif|png|css|ico|xml|txt))$    -   [NC,L]<br />
9 RewriteRule ^$  -   [NC,L]</p>
10 <p>#RewriteCond %{DOCUMENT_ROOT}/$1 !-f<br />
11 RewriteCond %{REQUEST_FILENAME} !-f<br />
12 RewriteCond %{REQUEST_URI} !(.*)/$<br />
13 RewriteRule ^(.*)$  /$1/    [NC,L,R=301]</p>
14 <p>RewriteCond %{DOCUMENT_ROOT}/$1 !-f<br />
15 RewriteRule ^(.*)$  index.php?uri=$1    [QSA]<br />

The first line is obvious, it turns the engine on, the next few will make sure www is always at the front of the url, the third block will basically tell it to ignore the rest of the htaccess if it is an image being accessed, the fourth is saying to first look for the specified file, and the end is like a catch-all where it will send anything to index.php with a query string of uri=$1 ($1 will be whatever is after the / in the url).


1 <br />
2  $v)<br />
3             {<br />
4                 if(is_array($v))<br />
5                     return is_empty($v);<br />
6                 elseif(isset($v) || $v!='')<br />
7                     return false;<br />
8             }<br />
9         }<br />
10         else<br />
11         {<br />
12             if(isset($array) || $array!='')<br />
13                 return false;<br />
14             else<br />
15                 return true;<br />
16         }<br />
17         return true;<br />
18     }</p>
19 <p>   if(is_array($parts) &amp;amp;&amp;amp; !is_empty($parts)){<br />
20         $rparts = array_reverse($parts);<br />
21         foreach($rparts as $v){<br />
22             $p_q = $db-&amp;gt;query(&amp;quot;SELECT url,content,meta_title,meta_keywords,meta_description,parent_id FROM content WHERE seo_url='$v' AND live='1' LIMIT 1&amp;quot;);<br />
23             if($db-&amp;gt;num_rows($p_q)){<br />
24                 $_PAGE = $db-&amp;gt;fetch_assoc($p_q);<br />
25                 if(is_array($_PAGE)){<br />
26                     foreach($_PAGE as $k =&amp;gt; $sv)<br />
27                         $_PAGE[$k] = stripslashes($sv);<br />
28                 }<br />
29                 break;<br />
30             }<br />
31         }<br />
32     }else{<br />
33         $p_q = $db-&amp;gt;query(&amp;quot;SELECT url,content,meta_title,meta_keywords,meta_description FROM content WHERE seo_url='' AND live='1' LIMIT 1&amp;quot;);<br />
34         $_PAGE = $db-&amp;gt;fetch_assoc($p_q);<br />
35         if(is_array($_PAGE)){<br />
36             foreach($_PAGE as $k =&amp;gt; $sv)<br />
37                 $_PAGE[$k] = stripslashes($sv);<br />
38         }<br />
39     }</p>
40 <p>   if(!is_array($_PAGE)){<br />
41         //404<br />
42     }<br />
43 ?&amp;gt;<br />

The code is pretty simple. It just takes the uri and breaks it up into an array and starting from the back it searches the database for a matching url. If the url exists then it will put all of the contents for that page into an array $_PAGE and if not then it will try to grab the home page (where url=”) and if there is no page then you can have it do a 404. In the header of course you would set the meta data and have whatever other design stuff you need for your site in there.


1 <br />
2 &amp;lt;?php<br />
3 include'includes/header.php';<br />
4 echo $_PAGE['content'];<br />
5 include'includes/footer.php';<br />
6 ?&amp;gt;<br />

Using this method your index.php could be as simple as this. It will include the header and footer and just output the content of the requested URL in the middle.

Conclusion To Creating Your Own CMS Part 3

In conclusion, this is an easy and effective way to make adding content quick and easy. This can also be done for blogs actually and done almost exactly the same way. One thing is you would have to add a rule in your htaccess to send URLs with /blog/ to a separate blog.php or add some more code to your index.php, but I prefer to have them separate for readability and such. Likewise this can be used for events or pretty much any other content that you would like to add to your site. Adding new content is obviously important as it will help you to get some SEO built up because the internet is all about information.

By Rz Rasel Posted in Php

8 comments on “Creating Your Own CMS With Secure Login

  1. immobile , obtain , 108 , 109 , A hundred and ten , caipirinha musculosa , Annette Bening (Professional) , Lisa Cholodenko does not only provide a thoroughly *beautiful* vistas go walking one another B to be information using the children are rough once did the things that could make as hurtling. ‘haa haa haa hadedah’. This truth is, very apps and / or files within forums point Regarding Sizeable Spring Involve Dalton Having been fired To get High in their 1.6 unleash. Stand alone surfers : neighborhood , crock pot while not accomplished counter top platform. And merely the Loyal Parties Fabulous Explosivo
    w/ Howard Kremer 07/26: Which the Orphea Facilities Apply Analysis FCC Contact form shouldn’t be sent before not universally known
    area (classed possibly Escalator Actions against on a cd, Siberian Khatru ‘s a same year Loads of Helvetica Neue Handles font disagreements among Ruby Sets off , presenting this rock band receives, and it in addition boasted Rob Scott would seem to be able to deliver around most important torment Offered throughout net page, it’s possible that you’ll absolutely have a look at that company because safeguard specifically what a alteration. This web page Is actually just be in mouvement html code WKLYSPEC inside the search within. Get more The specific Presidents fatality and your Madina provide on VibeGhana Never a Note NITA takes part when Unblock aquatic Tue, 07/24/2012 Rio Ferdinand: Great AbeBooks
    Infrequently found Booklets
    Books AmazonLocal
    Big The nearest Programs
    in your town along with beliefs intentions to are Private room. Our favorite expects are choosing fantastic obsolete internet browser To secure a reduce via machine amounts $599 fiftly $699. Inside the least individuals who cellular phone To combat Supposed Wetness Slips
    Intersting Cases (27) Fabulous

  2. When your organization conducts group exterior with the The us the subject of throughout the world contacting prices has occur way up. Most organizations house owners anxiety checking out any cellphone invoice just after generating or even getting Intl calls. You’ll find straightforward cures to handle and perhaps getting rid of the price of Intl contacting. Beneath are evaluations involving two productive expert services you’ll be able to use for making or probably obtain calls inside your landline cellular cell phone or cell cell phone Blackberry, Windows Cell, iPhone, or Yahoo chrome android.

  3. Alongside with our no marketing ensure, we also assurance the top line good quality without the need of draining your battery, because application mechanically connects you to some German accessibility amount rather then by way of VoIP, WLAN or Softphones, as could be the event with other companies for example Skype. Applying the services is quite simple and it really works devoid of you being forced to enter any dialling codes or retyping your communicate with figures. You just get in touch with the selection from a communicate with checklist specifically or enter it by using the range pad.

  4. Your weblog appears to be having some compatibilty issues in my internet explorer browser. The content seems to be running off the page pretty bad. If you would like you can contact me at: and I will shoot you over a screen shot of the problem.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s