How can I add user/access levels to my current login script?

9.6k views Asked by At

I'm currently learning PHP and MySQL and I have been working from a basic (albeit old) login script tutorial - I've come across various depreciated functions and such and I'm trying to improve on this script.

I would like to add different access levels to my script such as admins and users. I have added a row in my 'users' table called 'access' whereby access will be be '1' for users and '9' for admins.

After some initial research it seems I need to be able to store the users access level in a session variable - is this the right way to go about it? If so, how would I retrieve this initially, when the user logs in?

Once the access level is stored in the session variable, how will I then be able restrict access to pages - using header redirects perhaps?

This is the current code I'm working with from functions.php

function checkLogin()
    {
    /* Check if user has been remembered */
    if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookpass'])){
        $_SESSION['username'] = $_COOKIE['cookname'];
        $_SESSION['password'] = $_COOKIE['cookpass'];
    }

    /* Username and password have been set */
    if(isset($_SESSION['username']) && isset($_SESSION['password']))
    {
    /* Confirm that username and password are valid */
    if(confirmUser($_SESSION['username'], $_SESSION['password']) != 0)
    {
    /* Variables are incorrect, user not logged in */
        unset($_SESSION['username']);
        unset($_SESSION['password']);
        return false;
    }
        return true;
    }
    /* User not logged in */
    else
    {
      return false;
    }
    }

And from login.php

if(isset($_POST['sublogin'])){
   /* Check that all fields were typed in */
   if(!$_POST['user'] || !$_POST['pass']){
      $errors .= "You didn't fill in a required field.<br/>\n";

   }


else{

    /* Once all fields are entered - perform form validation */


   /* Checks that username is in database and password is correct */
   $md5pass = md5($_POST['pass']);
   $result = confirmUser($_POST['user'], $md5pass);

   /* Check error codes */
   if($result == 1){
      $user_errors .= "That username doesn't exist in our database.<br/>\n";
   }
   else if($result == 2){
      $pass_errors .= "Incorrect password, please try again.<br/>\n";
   }


   /* Username and password correct, register session variables */
   if (empty($errors) && empty($user_errors) && empty($pass_errors)){
        $_POST['user'] = mysql_real_escape_string($_POST['user']);
        $_SESSION['username'] = $_POST['user'];
        $_SESSION['password'] = $md5pass;
        /* Quick self-redirect to avoid resending data on refresh */
        echo "<META HTTP-EQUIV='refresh' CONTENT='0;URL=index.php'>";
   } 



   /**
    * This is the cool part: the user has requested that we remember that
    * and one to hold his md5 encrypted password. We set them both to
    * he's logged in, so we set two cookies. One to hold his username,
    * expire in 100 days. Now, next time he comes to our site, we will
    * log him in automatically.
    */
   if(isset($_POST['remember'])){
      setcookie("cookname", $_SESSION['username'], time()+60*60*24*100, "/");
      setcookie("cookpass", $_SESSION['password'], time()+60*60*24*100, "/");
    }

    //return;
}
}

Any help would be really appreciated as I've been stuck on this for a few days now, thanks.

2

There are 2 answers

2
Francis Yaconiello On BEST ANSWER

So this ex assumes that you are checking the limiting resources to roles in your PHP not from the DB. This can be easily changed, but i figured i'd make this ex a little simple.

Schema:

users
-------
id_user
identity
credential
role
... other fields

Account Creation

don't use md5, its easy to implement, and easily overcome. sha is just a litttle more secure with no additional work.

$email_or_username = "[email protected]";
$password = "PinkEleph4nt"; // not my real password for anything
$role = "admin";
$sql = sprintf("INSERT INTO users SET identity='%s', credential='%s', role='%s'",
    mysql_real_escape_string($email_or_username), 
    mysql_real_escape_string(sha1($password)), 
    mysql_real_escape_string($role));

Account Login

This is shortened, i threw the query in, but not alot of the DB logic, write it as its needed, read the comments.

// VALIDATE THE EMAIL/USERNAME and PASSWORD

if($is_valid == TRUE)
{
    $sql = sprintf("SELECT id_user FROM users WHERE identity='%s' AND credential='%s' LIMIT 1",
        mysql_real_escape_string($email_or_username), 
        mysql_real_escape_string(sha1($password)));

    // FETCH ROW save into $row

    if(!empty($row))
    {
        // A user was fetched save it into the session
        $_SESSION['id_user'] = $row['id_user'];

        // SUCCESS
    }
    else
    {
        // FAILURE
    }
}

Check user's role

<?php
function fetch_role()
{
    $role = "guest";
    if(isset($_SESSION['id_user']))
    {
        // User exists
        $sql = sprintf("SELECT * FROM users WHERE id_user='%s' LIMIT 1",
            mysql_real_escape_string($_SESSION['id_user']));

        // RUN THE MYSQL QUERY TO FETCH THE USER, SAVE INTO $row

        if(!empty($row))
        {
            $role = $user_row['role'];
        }
    }

    return $role;
}

...

$role = fetch_role();
if($role == 'guest')
{
    // SHOW GUEST CONTENT
}
elseif($role == 'member')
{
    // SHOW OTHER CONTENT
}
elseif($role == 'admin')
{
    // SHOW ADMIN CONTENT
}
0
r15habh On

Assign different role ids to different type of users in your user table. Have a context table which will store info of different file paths (preferably top most level of the required hierarchy in folder). And a table containing mapping between roles and different file paths (i.e. which type of user is allowed to access which path)
Now at the top of restricted files, have a util method which will take in __FILE__ path and role id and will tell whether the user have access permission or not and thus take relevant action. So you only need to store role id in session variable.