Comparison of strpos() variables - PHP

Asked

Viewed 249 times

0

I need some help between levels of access, I’ll post some of the code. It is a connection in AD (Active Diretory), authenticating the user and searching to which group he belongs.

This is the login code.php

    <?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 screen of Auth.php

<?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 you belong to group1 take the page of group1, If it belongs to Grupo2 takes the Grupo2 page.

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

If anyone can give 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");
            }

?>

That the login:

  • Ever tried to trade & for && when checking if the user belongs to the two groups? By the way, what is the value of $grps? If he starts with ACESSO_1 or ACESSO_2, the function strpos will return 0 and to the if this will be false.

2 answers

1

Good night!

Well, come on, I think your mistake is time to check if the user belongs to the two groups (& instead of &&) and, in addition, you break the loop if it is the third option (1 and 2). But regardless, why don’t 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 he had if/elseif/elseif/Else, he would check the first condition only once and, if true, 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;
}
  • In its logic, if the user belongs to both groups, would only enter the first if, defining $access = 1, leaving it only in group 1. That is, it does not work. In fact, the code does not solve the problem of the question when used strpos.

  • @Andersoncarloswoss true, but just change the order of ifs

  • @Andersoncarloswoss had not seen his comment in the author’s question, well noted. If a variable was created $group3 = "ACESSO_1 ACESSO_2"; and if made with only one condition would not solve?

  • As well "only one condition"?

  • Resolved as @Andersoncarloswoss, indicated.

  • @Andersoncarloswoss - I didn’t clear, the correct answer is the bottom one, which was already marked. And I voted for both answers, because they both helped me with the result, thank you very much.

Show 1 more comment

1


The function strpos searches a text in another and returns the position of the beginning if it is found or false otherwise. The problem of doing:

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

Is that if the value of $x start with the value of $y, the function will return 0 and the PHP interpreter will consider as false, even if the text has been found. See the example:

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

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

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

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

Thus, even if the return is 0, the condition will be true. In your case, it is possible to 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 be worth 3, because the two conditions will be true.


If there are many groups, it will be easier to work with binary values than integers. For example, let’s assume there are three groups, then 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 application page 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 the logic of the sum, it would be possible to define a different value for each situation: if it is only in group 3 the value 3 and if it is in groups 1 and 2 the value 4. But what if it is in groups 1 and 3? Another value, 5. What if it is in groups 2 and 3? Another value, 6. What if it is in groups 1, 2 and 3? Another value, 7. Can you imagine the amount of if? Imagine then if there are 4 groups.

Working with binary values, you set a power of 2 for each group. For example: group 1 is value 1 (2 0), group 2 is value 2 (2 1) and group 3 is value 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;
}

Just changing the operator += for |=, which is the or binary. So, to check if the user belongs to any group, just do the "and binary" with the group value.

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

And can merge 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
  • Baita lesson, explanation grade 10, I will check and study your answer and as soon as possible, I will return, by enqto thanks @Anderson Carlos Woss

  • @Marcelorossi and it worked?

  • No!!! I’m all morning here! I’ll try to post an answer by improving my question.

  • @Marcelorossi does not do this. Use the [edit] of the question itself to add relevant information.

    • edited my question and entered the full code. is still returning me only 1 of the screens. thank you if you help me.
  • @Marcelorossi and what is the value of $grps in the test you did? And do not use else if. See that in my answer are two if separated.

  • $gprs is $info[0]['memberof'] - or memberof (user)

  • But what is the value of the variable?

  • is the $info = ldap_get_entries($ldap, $result); = $info[0]['memberof'] - which seeks the results in the $result = ldap_search($ldap,"$grupolda",$filter);´ - e faz o filtro buscando o usuário no grupo pelo username$filter="(sAMAccountName=$username)";`

  • SOLVED - thanks to @Anderson Carlos Woss - simply insert the $access = 0; before the is, because if you are inside the is always will return 0.

  • All right Carlos, coming back here to this problem, how do I add 2 more groups to this process? Acesso 1 = Grupo 1 | &#xA;Acesso 2 = Grupo 2 | &#xA;Acesso 3 = Grupo 1 e Grupo 2 | &#xA;Acesso 4 = Grupo 4 | &#xA;Acesso 5 = Grupo 5 |&#xA;Acesso 6 = Grupo 4 e Grupo 5 | &#xA;Acesso 7 = Grupo 1 e Grupo 2 e grupo 4 e Grupo 5. I tried to use |= access failed, and did not understand the process of using the &, this is to use in procge.php - I could clarify better how I could do this?

  • Sorry to reschedule you again, follow my doubt in the above question.

  • @Marcelorossi I had already commented on this in the reply: group 4 should have the value 8 and group 5 the value 16.

Show 9 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.