Mevia
Mevia

Reputation: 1564

PHP logical operators "&&" and "||" while building simple security function

A few days ago I started implementing simple security function to my project to prevent users from viewing customers added to database by other users. When I was doing this, I got confused because I realized that standard logical operators works in weird way.

This is the code I initially wrote:

if($current_user_id != $session_user_id || access_level($session_user_id) != 3) {
    header('Location: logout.php');
    exit();
}

It means that if stored customer that you are trying to view doesn't belong to You or Your access level isn't 3 (administrator) you will be logged out. It should work according this:

http://www.w3schools.com/php/php_operators.asp

They say that || means "True if either condition 1 or condidtion 2 is true", so if any of conditions doesn't fail it should allow access. Of course it isn't, script behave as only first condition is written, meaning if you are admin so your access level is 3 and you are viewing not your customer - you still will be logged out.

This is minor modification that started to work:

if($current_user_id != $session_user_id && access_level($session_user_id) != 3) {
    header('Location: logout.php');
    exit();
}

After switching to && which means "True if both condition 1 and condition 2 are true" it started to work correctly, meaning you might not be owner of customer but if you are admin you will be allowed to access and not logged out.

At this point I'm afraid I understand it backwards, could someone explain why it doesn't seem logical? And how exactly it works? Thank you in advance.

Upvotes: 3

Views: 391

Answers (5)

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324750

Your logic is that the user should be allowed access if:

  • They are the owner, OR
  • The are an administrator

By this logic, you might construct this statement:

if( $user == $owner || access_level($user) == 3) {
    // allow access
}

But you're using the negative position, ie. disallowing access if they are NEITHER the owner NOR an administrator. This means you have to negate the entire if statement.

Looking at the truth tables for || and &&:

A B A||B A&&B
0 0  0    0
0 1  1    0
1 0  1    0
1 1  1    1

You can see from this that in order to get the opposite of A||B, we need !A && !B:

A B !A !B A||B !A&&!B
0 0 1  1   0     1
0 1 1  0   1     0
1 0 0  1   1     0
1 1 0  0   1     0

So to write this, you do the following:

if( !($user == $owner) && !(access_level($user) == 3) ) { /* deny access */ }

Which can of course be written as:

if( $user != $owner && access_level($user) != 3) { /* deny access */ }

Upvotes: 6

Barmar
Barmar

Reputation: 781721

Suppose $current_user_id = 3, $session_user_id = 5, and access_level($session_user_id) level = 3. That means $current_user_id != $session_user_id is true, and access_level($session_user_id) != 3 is false. || is true if either of the conditions is true, so the if succeeds and the user is logged out.

Or suppose $current_user_id = 3, $session_user_id = 3, and access_level($session_user_id) level = 2. That means $current_user_id != $session_user_id is false, and access_level($session_user_id) != 3 is true. Again, this means the || is true, so the if succeeds and the user is logged out.

Upvotes: 0

mpen
mpen

Reputation: 283043

This:

it means that if stored customer that you are trying to view doesnt belong to You or Your access level isnt 3 (administrator) you will be logged out.

Does not entail this:

if any of conditions doesnt fail it should allow access

See De Morgan's law.

The first statement is essentially (!a || !b). Negating that (i.e., !(!a || !b)) actually switches to operator to become: (a && b).

Therefore, your second statement should read:

if both of the conditions don't fail, the user should be allowed to access [whatever]

Upvotes: 3

Lawrence Cherone
Lawrence Cherone

Reputation: 46620

In your first example your using the OR operator but expecting to match 2 conditions for the following code, but one or the other could be matched.

E.G so if the user is not user level 3 it will logout regardless if $current_user_id != $session_user_id or visa versa.

Using the AND operator means both conditions must be matched before logging out.

Upvotes: 0

Denys Vitali
Denys Vitali

Reputation: 530

Well, here you are:

$a && $b means that the condition is true if $a and $b are set to true.

$a || $b means that $a or $b (or both) must be set to true.

!$a && $b means that $a must be false and $b must be true

!$a || $b means that $a must be false or $b must be true

$a != $b means that $a must be not equal to $b

$a == $b means that $a must be equal to $b

$a > $b means that $a must be greater than $b

$a < $b means that $a must be less than $b

and so on...

They are Comparison Operators, check it out!

Upvotes: 0

Related Questions