DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Databases
  4. Access Control with Bit Masks

Access Control with Bit Masks

Andrey Prikaznov user avatar by
Andrey Prikaznov
·
Dec. 30, 11 · Interview
Like (0)
Save
Tweet
Share
7.73K Views

Join the DZone community and get the full member experience.

Join For Free
Today I want to tell you about the organization of access rights for users (on your site) using bit masks. Perhaps you already know it, probably not, but anyway I want to give you this information. Why bit masks? – easy, because this is a fast and easy way to recognize a user’s possible actions. In our system, I have identified six possible actions (it will keep 6 bits, where each bit is one of the possible actions). The actions are: Read, Create, Edit Own, Delete Own, Edit Any and Delete Any (moderator’s / admin’s actions). This method can be applied to everything – blogs, news articles, photos and more. Ok, lets start.

Here is a little theory about Bitwise Operators:

ExampleNameResult
$a & $bAndBits that are set in both $a and $b are set.
$a | $bOr (inclusive or)Bits that are set in either $a or $b are set.
$a ^ $bXor (exclusive or) Bits that are set in $a or $b but not both are set.
~ $aNot Bits that are set in $a are not set, and vice versa.
$a << $bShift left Shift the bits of $a $b steps to the left (each step means “multiply by two”)
$a >> $bShift right Shift the bits of $a $b steps to the right (each step means “divide by two”)

Live Demo

download in package


Now – download the source files and lets start coding !


Step 1. HTML

Our demo uses 3 html template files:

main_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Access Control with Bit Masks</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <header>
        <h2>Access Control with Bit Masks</h2>
        <a href="http://www.script-tutorials.com/access-control-with-bit-masks/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="container">
        {form}
    </div>
</body>
</html>

This is a very easy layout, isn’t it?. Next template file:

login_form.html

<div class="column">
    <h3>Access control demonstration</h3>
    <p>You can use next usernames "User", "Writer", "Moderator" and "Admin" and password "password" to login in system. Each of them have own set of possibilities.</p>
</div>
<div class="column">
    <form class="login_form" action="index.php" method="post">
        <h3>Log In</h3>
        <label>Username:</label><input type="text" name="username">
        <label>Password:</label><input type="password" name="password">
        <input type="submit" name="LogIn" value="Login">
    </form>
</div>

Another one easy template for the login form. Next template file:

logout_form.html

<div class="column">
    <h3>Hello {name}</h3>
    <h3>Your bit mask:</h3>
    <div>{bit_mask}</div>
    <h3>Your possibilities:</h3>
    <div>{possibilities}</div>
</div>
<div class="column">
    <a href="index.php?logout">Log Out</a>
</div>

This is a template where we will display the user's possibilities and link to the logout.

Step 2. CSS

css/main.css

This file contains several styles of our page layout, no need to publish it today.

Step 3. PHP

Now, let's review our main functionality:

index.php

<?php

// define bit mask for access rights
define('CAN_READ', 1 << 0);   // 000001
define('CAN_CREATE', 1 << 1); // 000010
define('CAN_EDIT_OWN', 1 << 2);   // 000100
define('CAN_DELETE_OWN', 1 << 3); // 001000
define('CAN_EDIT_ANY', 1 << 4);   // 010000
define('CAN_DELETE_ANY', 1 << 5); // 100000

// login system init and generation code
$oSimpleAccessSystem = new SimpleAccessSystem();
$sLoginForm = $oSimpleAccessSystem->getLoginBox();
echo strtr(file_get_contents('main_page.html'), array('{form}' => $sLoginForm));

// class SimpleAccessSystem
class SimpleAccessSystem {

    // variables
    var $aMembers; // Existed members array

    // constructor
    function SimpleAccessSystem() {
        session_start();

        // different sets of permissions
        $sUserPerm = CAN_READ;
        $sWriterPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN;
        $sModeratorPerm = CAN_READ | CAN_EDIT_ANY | CAN_DELETE_ANY;
        $sAdminPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN | CAN_EDIT_ANY | CAN_DELETE_ANY;

        /* hash = sha1(md5('password') . 'testing'); */
        $this->aMembers = array(
            'User' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sUserPerm),
            'Writer' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sWriterPerm),
            'Moderator' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sModeratorPerm),
            'Admin' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sAdminPerm)
        );
    }

    // get login box function
    function getLoginBox() {
        if (isset($_GET['logout'])) { // logout processing
            if (isset($_SESSION['member_name']) && isset($_SESSION['member_pass']))
                $this->performLogout();
        }

        if ($_POST && $_POST['username'] && $_POST['password']) { // login processing
            if ($this->checkLogin($_POST['username'], $_POST['password'], false)) { // successful login
                $this->performLogin($_POST['username'], $_POST['password']);
                header( "Location:{$_SERVER['REQUEST_URI']}" );
                exit;
            } else { // wrong login
                ob_start(); // get template of Login form
                require_once('login_form.html');
                $sLoginForm = ob_get_clean();
                return $sLoginForm . '<h2>Username or Password is incorrect</h2>';
            }
        } else { // in case if we already logged (on refresh page):
            if (isset($_SESSION['member_name']) && $_SESSION['member_name'] && $_SESSION['member_pass']) {
                if ($this->checkLogin($_SESSION['member_name'], $_SESSION['member_pass'])) {
                    $sRule = $this->aMembers[$_SESSION['member_name']]['rule'];
                    $sPermissions = '';
                    $sPermissions .= $this->isCanRead($sRule);
                    $sPermissions .= $this->isCanCreate($sRule);
                    $sPermissions .= $this->isCanEdit($sRule);
                    $sPermissions .= $this->isCanEditAny($sRule);
                    $sPermissions .= $this->isCanDelete($sRule);
                    $sPermissions .= $this->isCanDeleteAny($sRule);

                    ob_start(); // get template of Logout form
                    require_once('logout_form.html');
                    $sLogoutForm = ob_get_clean();
                    $sLogoutForm = str_replace('{name}', $_SESSION['member_name'], $sLogoutForm);
                    $sLogoutForm = str_replace('{bit_mask}', $sRule, $sLogoutForm);
                    $sLogoutForm = str_replace('{possibilities}', $sPermissions, $sLogoutForm);
                    return $sLogoutForm;
                }
            }

            // otherwise - draw login form
            ob_start();
            require_once('login_form.html');
            $sLoginForm = ob_get_clean();
            return $sLoginForm;
        }
    }

    // check functions
    function isCanRead($sRule) {
        return ($sRule & CAN_READ) ? 'You can Read<br />' : '';
    }
    function isCanCreate($sRule) {
        return ($sRule & CAN_CREATE) ? 'You can Create<br />' : '';
    }
    function isCanEdit($sRule) {
        return ($sRule & CAN_EDIT_OWN) ? 'You can Edit<br />' : '';
    }
    function isCanEditAny($sRule) {
        return ($sRule & CAN_EDIT_ANY) ? 'You can Edit anything<br />' : '';
    }
    function isCanDelete($sRule) {
        return ($sRule & CAN_DELETE_OWN) ? 'You can Delete<br />' : '';
    }
    function isCanDeleteAny($sRule) {
        return ($sRule & CAN_DELETE_ANY) ? 'You can Delete anything<br />' : '';
    }

    // perform login
    function performLogin($sName, $sPass) {
        $this->performLogout();

        $sSalt = $this->aMembers[$sName]['salt'];
        $sPass = sha1(md5($sPass) . $sSalt);

        $_SESSION['member_name'] = $sName;
        $_SESSION['member_pass'] = $sPass;
    }

    // perform logout
    function performLogout() {
        unset($_SESSION['member_name']);
        unset($_SESSION['member_pass']);
    }

    // check login
    function checkLogin($sName, $sPass, $isHash = true) {
        if (isset($this->aMembers[$sName])) {
            if (! $isHash) {
                $sSalt = $this->aMembers[$sName]['salt'];
                $sPass = sha1(md5($sPass) . $sSalt);
            }
            return ($sPass == $this->aMembers[$sName]['hash']);
        }
        return false;
    }
}

First, we define the constants for access rights (bit mask). Further, when we enumerate users on the system – we grant them different sets of rights (using the logical operator | or). Keep in mind that I am not forcing you to keep users in the same array, in your case, your users can easily be in the database. And, in this case, you can grant them their right in the database itself. Further, I have added extra check functions, so that we can understand if the user can perform a certain action.

In such functions we use the logical operator & (and). Most of these checks use a single bit check. If you want to do multiple check, for example – let's create a function to check if the member can read and create. Then this function will looks like this:

function isCanReadCreate($sRule) {
    return ($sRule & (CAN_READ | CAN_CREATE));
}

This function will return True or False.


Live Demo

download in archive


Conclusion

I hope that it was interesting for you to remember how bitwise and logical operands work. If you have any good ideas you would like to share, be sure to write us as well. Good luck!

 

Source: http://www.script-tutorials.com/access-control-with-bit-masks/

Database

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Cloud Performance Engineering
  • How To Choose the Right Streaming Database
  • gRPC on the Client Side
  • Full Lifecycle API Management Is Dead

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: