2011-12-31 4 views
0

Я модифицировал систему аутентификации пользователей, и у меня возникли проблемы с настройкой сеанса для администратора. Сессия reguser устанавливается очень хорошо, но я не могу понять, почему admin не будет установлен.Установка переменной сеанса из результата запроса

Пользователь с userlevel из 9 - администратор. Да, я знаю, как защитить от SQL-инъекции. Я просто стараюсь держать его таким простым и легким для чтения. Это, вероятно, не будет использоваться ни для чего, я просто получаю некоторый опыт работы с PHP.

Привет всем, спасибо вам за помощь! Я заработал. Я так долго смотрел на него, что мой разум не был ясен. Вчера вырвался из него, вернулся к нему сегодня и смог понять это менее чем за 5 минут! Вы, ребята, потрясающие, я люблю stackoverflow!

function checklogin($email, $pass) { 
     $server = 'localhost'; 
     $user = 'root'; 
     $password = ''; 
     $connection = mysql_connect($server, $user, $password) or die(mysql_error()); 
     mysql_select_db(udogoo, $connection) or die(mysql_error()); 
     $pass = md5($pass); 
     $result = mysql_query("SELECT userid from users WHERE email = '$email' AND password = '$pass'"); 
     $user_data = mysql_fetch_array($result); 
     $no_rows = mysql_num_rows($result); 
     if ($no_rows == 1) 
    { 
     $_SESSION['reguser'] = true; 
     $_SESSION['userid'] = $user_data['userid']; 
     $userid = $user_data['userid']; 
     $isadmin = mysql_query("SELECT userlevel FROM users WHERE userid = '$userid'"); 
     $isadmin2 = mysql_fetch_array($isadmin); 
     $isadmin3 = $isadmin2['userlevel']; 
     if ($isadmin3 == "9"){ 
     $_SESSION['admin'] = true; 
     return true; 
    } 
    } 
     else 
    { 
     return FALSE; 
    } 
} 
+0

Ну, для начала, '$ result' является [ресурс вернулся из' mysql_query() '] (HTTP: // PHP. net/manual/en/function.mysql-query.php), поэтому ваше включение его в 'SELECT userlevel ...' на самом деле не ищет 'userid', как вы думаете. Вероятно, он ищет идентификатор ресурса # XX или что-то в этом роде. –

+0

Вместо использования простого значения 'md5()' для пароля вы можете посмотреть в ['crypt()'] (http://php.net/manual/en/function.crypt.php), используя 'CRYPT_BLOWFISH 'hash type with salt value, что значительно упрощает сохранение паролей. –

ответ

1
$userid = $user_data['user_id']; 
$isadmin = mysql_query("SELECT userlevel FROM users WHERE userid = $userid"); 

$user_data = mysql_fetch_array($result); 
$userlevel = $user_data['userlevel']; 

if($userlevel == '9') 
{ 
    $_SESSION['admin'] = true; 
} 

так, ваш полный код выглядеть следующим образом ::

<?php 
function checklogin($email, $pass) 
{ 
     $server = 'localhost'; 
     $user = 'root'; 
     $password = ''; 
     $connection = mysql_connect($server, $user, $password) or  die(mysql_error()); 
     mysql_select_db(test, $connection) or die(mysql_error()); 
     $pass = md5($pass); 
     $result = mysql_query("SELECT userid from users WHERE email = '$email' AND password = '$pass'"); 
     $user_data = mysql_fetch_array($result); 
     $numrows = mysql_num_rows($result); 
     if ($numrows == 1) 
     { 
      $_SESSION['reguser'] = true; 
      $_SESSION['userid'] = $user_data['userid']; 

      //MY ANSWER START HERE 
      $userid = $_SESSION['userid']; 
      $isadmin = mysql_query("SELECT userlevel FROM users WHERE userid = $userid"); 

      $user_data = mysql_fetch_array($result); 
      $userlevel = $user_data['userlevel']; 

      if($userlevel == '9') 
      { 
       $_SESSION['admin'] = true; 
      } 
      //END HERE 

     } 
     else 
     { 
      return false; 
     } 
} 

?> 
+0

Я пробовал что-то похожее на это раньше, и это не сработало. Странная часть - это почти то же самое, что и сеанс «регюзера». – user1104854

+1

Возможно, 'user_id' является буквенно-цифровым полем, поэтому может потребоваться' '$ userid''. Но, похоже, это связано с очевидной ошибкой использования '$ result' для поиска. –

+0

@JaredFarrish, спасибо за правильный ответ. да ты прав. –

3

У вас есть return true;, если существует пользовательские данные. Фактически, вы проверяете или администрируете только если пользователь не имеет.

Удалите это return true;, так как он здесь не нужен. Если хотите, добавьте else return false; после проверки наличия пользователя и return true; прямо в конце.

+0

Да, это еще одна проблема. Хороший улов. –

+0

+1 для улова. –

3

Ваша логика ошибочна, а также, здесь:

function checklogin($email, $pass) 
{ 
    $server = 'localhost'; 
    $user = 'root'; 
    $password = ''; 
    $connection = mysql_connect($server, $user, $password) or die(mysql_error()); 
    mysql_select_db(test, $connection) or die(mysql_error()); 

    $email = mysql_real_escape_string($email); 
    $pass = md5($pass); 

    $sql = "SELECT `userid`,`userlevel` 
      FROM `users` 
      WHERE `email` = '$email' 
      AND `password` = '$pass' 
      LIMIT 1"; //I certainly hope you check email for injection before passing it here. Also want the LIMIT 1 on there because you are only expecting a single return, and you should only get one since `email` should be unique since you're using it as a credential, and this will stop it from looking through all the rows for another match once it finds the one that matches. 

    $result = mysql_query($sql); 

    $user_data = mysql_fetch_array($result); 
    $numrows = mysql_num_rows($result); 

    if ($numrows == 1) 
    { 
     $_SESSION['reguser'] = true; 
     $_SESSION['userid'] = $user_data['userid']; 

     if($user_data['userlevel'] == 9) 
     { 
      $_SESSION['admin'] = true; 
     } 
     else 
     { 
      $_SESSION['admin'] = false; 
     } 
     return true; 
    } 
    return false; 
} 

Это должно работать. Нет веских оснований делать два запроса, когда все будет хорошо. Возвращает true, если пользователь вошел в систему, false, если пользователь не существует или учетные данные не совпадают.

Ошибка, небольшая синтаксическая ошибка в инструкции SQL, исправлена. Также исправлена ​​большая синтаксическая ошибка.

А вот как сделать верхнюю часть в PDO:

function checklogin($email, $pass) 
{ 
    $server = 'localhost'; 
    $user = 'root'; 
    $password = ''; 
    $dbname = 'test'; 
    $dsn = 'mysql:dbname=' . $dbname . ';host=' . $server; 

    $conn = new PDO($dsn,$user,$password); //Establish connection 

    $pass = md5($pass); 

    $sql = "SELECT `userid`,`userlevel` 
      FROM `users` 
      WHERE `email` = :email 
      AND `password` = :pass 
      LIMIT 1"; 

    $stmt = $conn->prepare($sql); 
    $stmt->bindParam(':email',$email,PDO::PARAM_STR,128) //First param gives the placeholder from the query, second is the variable to bind into that place holder, third gives data type, fourth is max length 
    $stmt->bindParam(':pass',$pass,PDO::PARAM_STR,32) //MD5s should always have a length of 32 

    $stmt->setFetchMode(PDO::FETCH_ASSOC); 
    $stmt->execute(); //almost equivalent to mysql_query 
    $user_data = $stmt->fetch(); //Grab the data 

    if(is_array($user_data) && count($user_data) == 2) //Check that returned info is an array and that we have both `userid` and `userlevel` 
    { 
     //Continue onwards 
+0

Вы можете продемонстрировать, как избежать адреса электронной почты (хотя OP действительно упоминает об экранировании в письме). Обратите внимание, что побег - это просто хорошая практика, не обязательно практика безопасности. –

+0

Действительно, поскольку это письмо, просто проверка его на наличие действительного формата электронной почты будет достаточным для его спуска. Невозможно представить какие-либо SQL-инъекции, которые вы можете поместить в формате [email protected] или [email protected] Я просто хочу, чтобы мои входы соответствовали тому, что они должны были использовать, и использовать PDO с подготовленными операторами и связанными параметрами и больше не беспокоиться об этом. – Phoenix

+1

Это необычный совет. Поскольку в примере и вашем ответе не используется PDO, побег - это требование. Несмотря на валидацию, в большинстве случаев входные данные в запросах следует избегать. –