You Are Here Home > How to write a permission system using bits and bitwise...

How to write a permission system using bits and bitwise operations in PHP

I wrote this in PHP but you can use the same concept in other languages, I also assume an understanding of bits, bytes, binary to decimal conversion and vice-versa and bitwise operations on numbers like ‘or’, ‘and’ and ‘xor’ etc. if you have no idea, search and read about these first. You don’t have to be a guru but you should have an idea. Here are some pages to get you started:

http://en.wikipedia.org/wiki/Byte
http://en.wikipedia.org/wiki/Bitwise_operation
http://us.php.net/manual/en/language.operators.bitwise.php
Some binary to decimal calculators to make it easier

We will use simple numbers to represent different permissions and as you might know a number is a collection of bytes. For example: an integer is usually 4 bytes. Although you don’t have to worry about the size of a number in a high level language like PHP but a little understanding of representation of numbers will help you better understand this technique.

So let’s assume when I say:

<?php
 
	$user_perms = 7;
 
?>

Internally the variable $user_perms looks like this:

|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|1|

This is a 2 byte representation of number 7, although, it might not look like this internally – it looks similar. Just assume this for now.

Let’s say that your application supports 4 functions that a user can use:

1 – Post a blog post
2 – Comment on blog posts
3 – Edit posts
4 – Delete posts

Normally, you could have 4 fields in your database table (structure or whatever) for a user titled:

1 – can_post
2 – can_comment
3 – can_edit
4 – can_delete

This is not good, 4 additional fields for your user table and who knows, what if your application has 100 functions? Do you want to add 100 fields to your user table?

With bits, you can have only 1 column and track all the permissions.

1 – perms

To do this, we will have to assign numbers for each of the functions: (Tip: use one of the calculators in the above list ;) )

1 – Post a blog post |0|0|0|0|0|0|0|1| is 1 in decimal
2 – Comment on blog posts |0|0|0|0|0|0|1|0| is 2 in decimal
3 – Edit posts |0|0|0|0|0|1|0|0| is 4 in decimal
4 – Delete posts |0|0|0|0|1|0|0|0| is 8 in decimal

So you could have an array like this:

<?php
 
	$perms = array(
		'can_post' => 1,
		'can_comment' => 2,
		'can_edit' => 4,
		'can_delete' => 8
	);
 
?>

Almost there, let’s look at user’s perms field now.

I hope you know about bitwise ‘or’, when you ‘or’ 1 and 1 you get 1; 0 ‘or’ 1 is 1; 1 ‘or’ 0, is 1 and finally 0 ‘or’ 0 is 0, it’s just like the meaning of ‘or’ in the English language.

Similarly, bitwise ‘and’; when you ‘and’ 1 and 1 you get 1; 0 ‘and’ 1 is 0; 1 ‘and’ 0, is 0 and finally 0 ‘and’ 0 is 0, again it’s just like the meaning of ‘or’ in the English language.

Bitwise ‘xor’; when you ‘xor’ 1 and 1 you get 0; 0 ‘xor’ 1 is 1; 1 ‘xor’ 0, is 1 and finally 0 ‘xor’ 0 is 0.

So suppose you want to give a user permissions to post a blog post, post a comment and edit posts but not delete posts, you do it like this:

<?php
 
	$user_perms = $perms['can_post'] | $perms['can_comment'] | $perms['can_edit'];
 
?>

Note that, in PHP ‘|’ means ‘or’, so what just happened is something like this:

|0|0|0|0|0|0|0|1| ‘or’
|0|0|0|0|0|0|1|0| ‘or’
|0|0|0|0|0|1|0|0|
_______________________
|0|0|0|0|0|1|1|1|

Now $user_perms has the value 7 and |0|0|0|0|0|1|1|1| in it internally.

Suppose that this is on top of your post_blog.php or where ever you want to handle permissions for posting a blog, the only thing you need to do is:

<?php
 
	if ($user_perms & $perms['can_post']) {
		/* He/She has permissios to do this */
	} else {
		/* He/She doesn't */
	}
 
?>

In PHP ‘&’ is for bitwise ‘and’, please also note that ‘&&’ is logical ‘and’ and doesn’t operate on individual bits.

This is exactly what just happened:

|0|0|0|0|0|1|1|1| ‘and’
|0|0|0|0|0|0|0|1|
_______________________
|0|0|0|0|0|0|0|1|

So that’s ‘one’ not ’0′, which means ‘if’ passes and the user has permissions to do this. But when it comes to deleting posts:

<?php
 
	if ($user_perms & $perms['can_delete']) {
		/* He/She does permissios to do this */
	} else {
		/* He/She doesn't */
	}
 
?>

Thus:

|0|0|0|0|0|1|1|1| ‘and’
|0|0|0|0|1|0|0|0|
_______________________
|0|0|0|0|0|0|0|0|

It’s ‘zero’ so ‘if’ fails and you show an error message or whatever it is you do.

To add ‘delete’ permissions, you use ‘or’ again:

<?php
 
	$user_perms |= $perms['can_delete'];
 
?>

So this happens:

|0|0|0|0|0|1|1|1| ‘or’
|0|0|0|0|1|0|0|0|
_______________________
|0|0|0|0|1|1|1|1|

To take away permissions you use ‘xor’:

<?php
 
	$user_perms ^= $perms['can_delete'];
 
?>

And this will happen:

|0|0|0|0|1|1|1|1| ‘xor’
|0|0|0|0|1|0|0|0|
_______________________
|0|0|0|0|0|1|1|1|

And delete permissions are gone!

Now let’s take away post permissions:

<?php
 
	$user_perms ^= $perms['can_post'];
 
?>

Thus:

|0|0|0|0|0|1|1|1| ‘xor’
|0|0|0|0|0|0|0|1|
_______________________
|0|0|0|0|0|1|1|0|

So this was just the basics, you can build on this and do more once you understand.

I hope this post will help someone :)

How to write a permission system using bits and bitwise operations in PHP
Filed under: PHP,Programming,Security,Web Development   Posted by: Hamid

10 Comments »

  1. Tom:
     

    Nice article, but does it mean that if you fix it this way, that you can only have 32 rights on a 32bit system and 64 rights on a 64bit system?

    Or does it work in another way?

    Comment

     
  2. Codehead:
     

    Yes, that is technically correct, so you could have permission groups maybe…

    I would assume 32 bits though, since you don’t know where your code is going to run.

    Comment

     
  3. Tom:
     

    I understand that..
    I asked it because I want to write a ACL class of my own.
    And bitwise is the easiest solution in this case. The bit limit is something I don’t like though

    Comment

     
  4. Codehead:
     

    If you have to track more that 32 permissions then you could have permission groups I guess…

    Comment

     
  5. Mendi:
     

    Thanks! This is a great help for me!! Good job!

    Comment

     
  6.  

    Fist of all it is a great example page to demonstrate the use of bitwise operators, but… implementing the example permission system this way is not as much flexible as it couud be in sql

    users (userid PK, etc…)
    permissiontypes (permid PK, etc)
    user_permission(userid FK, permissiontype FK)

    You would have much easier code on the long rin and implementing the mentioned group (role) based authentication is a breeze.

    And yes, of course it is way better to wrap it with a permission class if you ever have to use a standard user/permission repository for example by LDAP.

    Comment

     
  7. Codehead:
     

    Do you mean keeping permissions in a database so you are not hard coding it?!

    If that’s what you mean, it’s OK to do it that way in situations where you need it otherwise you should always keep it simple…

    Of course, permissions for each individual user should be kept in the database.

    Comment

     
  8. tahir:
     

    Thanks for the great article.
    Can we use the similar approach to design the field/object level security and plug this with the customized security manager ?

    Comment

     
  9. Codehead:
     

    I’m not exactly understanding your question but if you mean what I think you mean then yes…

    Comment

     
  10. tahir:
     

    Thanks for the quick repoly.

    Infact i wanted to design a customized security module which can work on fields level. meaning every field in my application can have enable/diable/visible flags that can be configured for each user/group.

    The idea is to use same technique (bitwise operators) which will eliminate defining hundereds of fields in my database and i will only define a few integer values for each user and screen combination.

    I have tried to simulate the same with the provided example, it worked but the real problem now is the 32 bit nature of Int in C# cannot possibly go beyond 32 fields at most.

    Any better thoughts for moving forward.

    Comment

     

RSS feed for comments on this post. TrackBack URL

Leave a comment