2011-12-31 10 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'、そもそもHTTP([リソースは'するmysql_query() 'から返さ]されます。 net/manual/en/function.mysql-query.php)、それを 'SELECT userlevel ...'に含めると、 'userid'で実際には探しているとは限りません。おそらく 'Resource ID#XX'か何かを探しています。 –

+0

パスワードに通常の 'md5()'値を使用する代わりに、 '' crypt() '](http://php.net/manual/en/function.crypt.php)を見て、' 'CRYPT_BLOWFISH 'ハッシュ型のソルト値を使用すると、パスワードの保存がより安全になります。 –

答えて

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 for catch .. –

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; 
} 

。 1つだけうまくいくときに2つのクエリを実行する正当な理由はありません。ユーザーがログインしている場合はtrue、ユーザーが存在しない場合、または資格が一致しない場合はfalseを返します。

SQL文で小さな構文エラーが修正されました。より大きい構文エラーも修正されました。

そして、ここであなたはPDOで上部を行う方法は次のとおりです。// PHP:

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を使用しないので、エスケープは事実上の要件です。検証にもかかわらず、クエリの入力はほとんどの場合エスケープする必要があります。 –

関連する問題