2011-12-31 7 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'에 의해 실제로 검색되는 것이 아닙니다. 아마'Resource ID # XX' 또는 무엇인가를 찾고있을 것입니다. –

+0

패스워드에 일반'md5()'값을 사용하는 대신에'CRYPT_BLOWFISH()를 사용하여 ['crypt()'] (http://php.net/manual/en/function.crypt.php) '해쉬 타입은 소금 값을 가지기 때문에 암호 저장이 훨씬 안전합니다. –

답변

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

이전과 비슷한 것을 시도했지만 작동하지 않았습니다. 이상한 부분은 "reguser"세션 설정 방법과 거의 동일합니다. – 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

정말 전자 메일이기 때문에 유효한 전자 메일 형식인지 확인하는 것만으로도 충분합니다. [email protected] 또는 [email protected] 형식으로 들어갈 수있는 SQL 주입을 생각할 수 없습니다. 나, 필자는 필자의 입력 내용이 자신이 원하는 것에 맞는지 확인하고 준비된 명령문 및 바인딩 된 매개 변수를 사용하여 PDO를 사용하므로 더 이상 걱정하지 마십시오. – Phoenix

+1

그건 특이한 조언입니다. 예와 답에서 PDO를 사용하지 않기 때문에 탈출은 사실상 요구 사항입니다. 유효성 검사에도 불구하고 쿼리의 입력은 대부분의 경우 이스케이프되어야합니다. –