Comparison between strpos () - PHP variables

0

I need help between levels of access, I'll post part of the code. It is a connection in Active Directory (AD), authenticating the user and searching to which group it belongs to.

This is the login.php code

    <?php
    include("auth.php");

    // check to see if user is logging out
    if(isset($_GET['out'])) {
        // destroy session
        session_unset();
        $_SESSION = array();
        unset($_SESSION['username'],$_SESSION['access']);
        session_destroy();
    }

    // check to see if login form has been submitted
    if(isset($_POST['username'])){
        // run information through authenticator
        if(authenticate($_POST['username'],$_POST['userPassword']))
        {
            header("Location: assets/procge.php");
            die();
        } else {
            $error = 1;
        }
    }

    ?>


<form action="#" class="form-signin" method="POST">

<h2 style="text-align:center; font-size: 18px;">Para acesso Telas BI, <br />realize o login.</h2>
<?php
if(isset($error)) echo "<div style='color:#ff0000; text-align:center;'>ERRO!<br /> Usuário e senha inválidos ou sem acesso.</div><br />";
if(isset($_GET['out'])) echo "Sucesso ao deslogar!!!";
 ?>
 <label for="inputEmail" class="sr-only">Usuário</label>
<input id="username" type="text" name="username" autocorrect="off" autocapitalize="off" class="form-control" placeholder="Usuário" /> 
 <label for="inputPassword" class="sr-only">Senha</label>
<input type="password" name="userPassword" id="password" autocomplete="off" class="form-control" placeholder="Senha">   
<input class="btn btn-success"  name="submit" value="Acessar" type="submit">
</form>

Here the Auth.php screen

<?php
function authenticate($username, $password) {
    if(empty($username) || empty($password)) return false;

$adServer = "ldap://10.10.100.23";
    $ldap = ldap_connect($adServer);
    $ldaprdn = 'dominio' . "\" . $username;
    $grupolda = 'DC=dominio,DC=com,DC=br';
    $grupo1 = 'grupo1';
    $grupo2 = 'grupo2';

    ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

    $bind = @ldap_bind($ldap, $ldaprdn, $password);

    if ($bind) {
        $filter="(sAMAccountName=$username)";
        $attr = array("memberof");
        $result = ldap_search($ldap,"$grupolda",$filter);
        ldap_sort($ldap,$result,"sn");

        $info = ldap_get_entries($ldap, $result);
          for ($i=0; $i<$info["count"]; $i++)      {
            if($info['count'] > 1)
                break;
           echo "<p>Acesso ao A.D. <strong> ". $info[$i]["givenname"][0]." ".$info[$i]["sn"][0] ."</strong><br /> </p>\n";

            $userDn = $info[$i]["distinguishedname"][0];
          }

          // check os grupos
             foreach($info[0]['memberof'] as $grps) {


    $access = 0;
    if(strpos($grps, $grupo1) !== false) {
    //Se pertence a esse grupo da acesso 1, somente a esse grupo
    $access += 1;   
    }

    elseif(strpos($grps, $grupo2) !== false) { 
    //Se pertence a esse grupo da acesso 2, somente a esse grupo    
    $access += 2;
    break;
    } 

      }
        if($access != 0) {
            // Cria as sessões do usuário
            $_SESSION['username'] = $username;
            $_SESSION['access'] = $access;
            return true;

        } else {
            $_SESSION['loginErro'] = $erro;
            // Sem direitos
            return false;
        }

    } else {
        // Usuário e senha inválidos
        return false;
    }
}
?>

When the user is in only one of the groups, it works, if it belongs to group1 it takes the page from group1, If it belongs to group2 it takes the page of group2.

But when it belongs to the two groups group1 and 2 with access 3, it always returns to one of the hits, leading to an individual page and not the page that should give access.

If someone can give you an orientation on how to proceed

This is procge.php

<?php
// initialize session
session_start();

    if($_SESSION['access'] == 1){
            header("Location:../grupo1/index.php");
            }
    if($_SESSION['access'] == 2){
            header("Location: ../grupo2/index.php");
            }
    if($_SESSION['access'] == 3){
            header("Location: ../grupo1e2/index.php");
            }
     else{
            $_SESSION['access'] !== "Erro! Sem permissão de acesso.";
         break;
                header("Location: ../index.php");
            }

?>

This is the login:

    
asked by anonymous 03.07.2017 / 22:58

2 answers

1

The function strpos searches text in another and returns the start position if it finds or false otherwise. The problem of doing:

if (strpos($x, $y)) { ... }

If the value of $x starts with the value of $y , the function returns 0 and the PHP interpreter will consider it false even if the text was found. See the example:

var_dump(strpos("Stack Overflow em Português", "Stack"));

The return will be int(0) . See working at Ideone .

The correct thing to do is to check if the return is not false. That is:

if (strpos($x, $y) !== false) { ... }

So, even if the return is 0, the condition is true. In your case, you can simplify only for two conditions:

$access = 0;

if (strpos($grps, $grupo1) !== false) {
    $access += 1;
}

if (strpos($grps, $grupo2) !== false) {
    $access += 2;
}

If the user belongs to both groups, the variable $access will count 3, since both conditions will be true.

If there are many groups, it will be easier to work with binary values than integers. For example, let's suppose there are three groups, so you make the condition:

$access = 0;

if (strpos($grps, $grupo1) !== false) {
    $access += 1;
}

if (strpos($grps, $grupo2) !== false) {
    $access += 2;
}

if (strpos($grps, $grupo3) !== false) {
    $access += 3;
}

But the other page of the application was accessed by a user with access equal to 3. And now, is he only in group 3 or is he in groups 1 and 2? Both situations would result in $access = 3 . Without using summation logic, it would be possible to define a different value for each situation: if only in group 3 is the value 3 and if in groups 1 and 2 is the value 4. But what if it is in groups 1 and 3? Another value, 5. What if you are in groups 2 and 3? Another value, 6. What if you are in groups 1, 2 and 3? Another value, 7. Can you imagine the amount of if ? Then imagine if there are 4 groups.

Working with binary values, you set a power of 2 for each group. For example: group 1 is 1 (2 → 0), group 2 is 2 (2 → 1) and group 3 is 4 (2 ^ 2). If there were more groups it would be 8 (2 ^ 3), 16 (2 ^ 4), 32 (2 ^ 5), etc. So you make the following conditions:

$access = 0;

if (strpos($grps, $grupo1) !== false) {
    $access |= 1;
}

if (strpos($grps, $grupo2) !== false) {
    $access |= 2;
}

if (strpos($grps, $grupo3) !== false) {
    $access |= 4;
}

Only by changing the += operator to |= , which is the or binary. So, to check if the user belongs to a group, just do the "and binary" with the value of the group.

if ($access & 1) { ... }  // Pertence ao grupo 1
if ($access & 2) { ... }  // Pertence ao grupo 2
if ($access & 4) { ... }  // Pertence ao grupo 3

And you can merge the values too:

if ($access & 3) { ... }  // Pertence aos grupos 1 e 2
if ($access & 5) { ... }  // Pertence aos grupos 1 e 3
if ($access & 6) { ... }  // Pertence aos grupos 2 e 3
if ($access & 7) { ... }  // Pertence aos grupos 1, 2 e 3
    
03.07.2017 / 23:50
1

Good evening!

Well, come on, I think your mistake is checking to see if the user belongs to the two groups (& & amp; & amp;) instead, and in addition you give a break in the loop if the third option (1 and 2). But regardless, why do not you use if / elseif / elseif / else instead of the three ifs in a row? In terms of performance, your program checks the 3 conditions every time it is run. If it had if / elseif / elseif / else, it would check the first condition only once, and if it was true, it would not check the others, avoiding unnecessary memory expenditure.

Rewriting your code (with the bug fixed) it would look like this:

    // tenho 2 grupos
     $grupo1 = 'ACESSO_1';
     $grupo2 = 'ACESSO_2';

    // check as informações do usuário e informa o grupo ao qual ele pertence
    foreach($info[0]['memberof'] as $grps) {


    // Verifica os grupos que pertence
    if(strpos($grps, $grupo1) && strpos($grps, $grupo2)) { 

    //se pertence ao 2 grupos da acesso aos 2 grupos acesso 3
    $access = 3; 
    } 
    elseif(strpos($grps, $grupo2)) { 

    //Se pertence a esse grupo da acesso 2, somente a esse grupo    
    $access = 2;
    } 
    elseif(strpos($grps, $grupo1)) {

    //Se pertence a esse grupo da acesso 1, somente a esse grupo
    $access = 1;   
    }
    else {
        $_SESSION['loginErro'] = $erro;
        // Sem direitos
        return false;
    }

    //Se o nível de acesso for diferente de 0 cria a sessão.
    // Cria as sessões do usuário
    $_SESSION['username'] = $username;
    $_SESSION['access'] = $access;
    return true;

} else {
    // Usuário e senha inválidos
    return false;
}
    
03.07.2017 / 23:31