Access Control with Bit Masks

Image Tutorials

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

Here are a little of theory about Bitwise Operators:

Example Name Result
$a & $b And Bits that are set in both $a and $b are set.
$a | $b Or (inclusive or) Bits that are set in either $a or $b are set.
$a ^ $b Xor (exclusive or) Bits that are set in $a or $b but not both are set.
~ $a Not Bits that are set in $a are not set, and vice versa.
$a << $b Shift left Shift the bits of $a $b steps to the left (each step means “multiply by two”)
$a >> $b Shift 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

01 <!DOCTYPE html>
02 <html lang="en" >
03 <head>
04     <title>Access Control with Bit Masks</title>
05     <link href="css/main.css" rel="stylesheet" type="text/css" />
06 </head>
07 <body>
08     <header>
09         <h2>Access Control with Bit Masks</h2>
10         <a href="https://www.script-tutorials.com/access-control-with-bit-masks/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
11     </header>
12     <div class="container">
13         {form}
14     </div>
15 </body>
16 </html>

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

login_form.html

01 <div class="column">
02     <h3>Access control demonstration</h3>
03     <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>
04 </div>
05 <div class="column">
06     <form class="login_form" action="index.php" method="post">
07         <h3>Log In</h3>
08         <label>Username:</label><input type="text" name="username">
09         <label>Password:</label><input type="password" name="password">
10         <input type="submit" name="LogIn" value="Login">
11     </form>
12 </div>

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

logout_form.html

01 <div class="column">
02     <h3>Hello {name}</h3>
03     <h3>Your bit mask:</h3>
04     <div>{bit_mask}</div>
05     <h3>Your possibilities:</h3>
06     <div>{possibilities}</div>
07 </div>
08 <div class="column">
09     <a href="index.php?logout">Log Out</a>
10 </div>

This is template where we will display our possibilities and link to 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, lets review our main functionality:

index.php

001 <?php
002 // define bit mask for access rights
003 define('CAN_READ', 1 << 0);   // 000001
004 define('CAN_CREATE', 1 << 1); // 000010
005 define('CAN_EDIT_OWN', 1 << 2);   // 000100
006 define('CAN_DELETE_OWN', 1 << 3); // 001000
007 define('CAN_EDIT_ANY', 1 << 4);   // 010000
008 define('CAN_DELETE_ANY', 1 << 5); // 100000
009 // login system init and generation code
010 $oSimpleAccessSystem new SimpleAccessSystem();
011 $sLoginForm $oSimpleAccessSystem->getLoginBox();
012 echo strtr(file_get_contents('main_page.html'), array('{form}' => $sLoginForm));
013 // class SimpleAccessSystem
014 class SimpleAccessSystem {
015     // variables
016     var $aMembers// Existed members array
017     // constructor
018     function SimpleAccessSystem() {
019         session_start();
020         // different sets of permissions
021         $sUserPerm = CAN_READ;
022         $sWriterPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN;
023         $sModeratorPerm = CAN_READ | CAN_EDIT_ANY | CAN_DELETE_ANY;
024         $sAdminPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN | CAN_EDIT_ANY | CAN_DELETE_ANY;
025         /* hash = sha1(md5('password') . 'testing'); */
026         $this->aMembers = array(
027             'User' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b''salt' => 'testing''rule' => $sUserPerm),
028             'Writer' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b''salt' => 'testing''rule' => $sWriterPerm),
029             'Moderator' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b''salt' => 'testing''rule' => $sModeratorPerm),
030             'Admin' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b''salt' => 'testing''rule' => $sAdminPerm)
031         );
032     }
033     // get login box function
034     function getLoginBox() {
035         if (isset($_GET['logout'])) { // logout processing
036             if (isset($_SESSION['member_name']) && isset($_SESSION['member_pass']))
037                 $this->performLogout();
038         }
039         if ($_POST && $_POST['username'] && $_POST['password']) { // login processing
040             if ($this->checkLogin($_POST['username'], $_POST['password'], false)) { // successful login
041                 $this->performLogin($_POST['username'], $_POST['password']);
042                 header( "Location:{$_SERVER['REQUEST_URI']}" );
043                 exit;
044             else // wrong login
045                 ob_start(); // get template of Login form
046                 require_once('login_form.html');
047                 $sLoginForm = ob_get_clean();
048                 return $sLoginForm '<h2>Username or Password is incorrect</h2>';
049             }
050         else // in case if we already logged (on refresh page):
051             if (isset($_SESSION['member_name']) && $_SESSION['member_name'] && $_SESSION['member_pass']) {
052                 if ($this->checkLogin($_SESSION['member_name'], $_SESSION['member_pass'])) {
053                     $sRule $this->aMembers[$_SESSION['member_name']]['rule'];
054                     $sPermissions '';
055                     $sPermissions .= $this->isCanRead($sRule);
056                     $sPermissions .= $this->isCanCreate($sRule);
057                     $sPermissions .= $this->isCanEdit($sRule);
058                     $sPermissions .= $this->isCanEditAny($sRule);
059                     $sPermissions .= $this->isCanDelete($sRule);
060                     $sPermissions .= $this->isCanDeleteAny($sRule);
061                     ob_start(); // get template of Logout form
062                     require_once('logout_form.html');
063                     $sLogoutForm = ob_get_clean();
064                     $sLogoutForm str_replace('{name}'$_SESSION['member_name'], $sLogoutForm);
065                     $sLogoutForm str_replace('{bit_mask}'$sRule$sLogoutForm);
066                     $sLogoutForm str_replace('{possibilities}'$sPermissions$sLogoutForm);
067                     return $sLogoutForm;
068                 }
069             }
070             // otherwise - draw login form
071             ob_start();
072             require_once('login_form.html');
073             $sLoginForm = ob_get_clean();
074             return $sLoginForm;
075         }
076     }
077     // check functions
078     function isCanRead($sRule) {
079         return ($sRule & CAN_READ) ? 'You can Read<br />' '';
080     }
081     function isCanCreate($sRule) {
082         return ($sRule & CAN_CREATE) ? 'You can Create<br />' '';
083     }
084     function isCanEdit($sRule) {
085         return ($sRule & CAN_EDIT_OWN) ? 'You can Edit<br />' '';
086     }
087     function isCanEditAny($sRule) {
088         return ($sRule & CAN_EDIT_ANY) ? 'You can Edit anything<br />' '';
089     }
090     function isCanDelete($sRule) {
091         return ($sRule & CAN_DELETE_OWN) ? 'You can Delete<br />' '';
092     }
093     function isCanDeleteAny($sRule) {
094         return ($sRule & CAN_DELETE_ANY) ? 'You can Delete anything<br />' '';
095     }
096     // perform login
097     function performLogin($sName$sPass) {
098         $this->performLogout();
099         $sSalt $this->aMembers[$sName]['salt'];
100         $sPass = sha1(md5($sPass) . $sSalt);
101         $_SESSION['member_name'] = $sName;
102         $_SESSION['member_pass'] = $sPass;
103     }
104     // perform logout
105     function performLogout() {
106         unset($_SESSION['member_name']);
107         unset($_SESSION['member_pass']);
108     }
109     // check login
110     function checkLogin($sName$sPass$isHash = true) {
111         if (isset($this->aMembers[$sName])) {
112             if (! $isHash) {
113                 $sSalt $this->aMembers[$sName]['salt'];
114                 $sPass = sha1(md5($sPass) . $sSalt);
115             }
116             return ($sPass == $this->aMembers[$sName]['hash']);
117         }
118         return false;
119     }
120 }

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 user can perform a certain action.

In such functions we use logic operator & (and). Most of these checks uses single bit check. If you want to make multiple check, as example – lets create function to check if member can read and create. Then this function will looks like this:

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

This function will return us True or False.


Live Demo
download in archive

Conclusion

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

Rate article