使用MySqli准备声明登录

时间:2017-05-26 11:46:26

标签: php mysqli prepared-statement login-script

我通过使用echo语句替换IF中的所有语句并检查其工作正常来检查我的代码。

if($rows==1){
    echo "Record exists in DB";
}

我不知道为什么$result = mysqli_stmt_get_result($stmt);返回false并且我收到错误

  

警告:mysqli_fetch_array()要求参数1为mysqli_result,布线在第57行的E:\ xampp \ htdocs \ _jq \ login_system_sql_injection_proof \ loginprocess.php中给出

我在互联网上搜索解决方案却浪费了一天多的时间,却没有找到任何解决方案。如果有人帮助我,我将非常感激。我期望以程序方式解决方案。在此先感谢

<?php require("dbconnect.php"); ?>

<?php

 $uname = $pass = "";

    if($_SERVER['REQUEST_METHOD']=='POST'){
        if(empty($_POST['uname'])){
            header("location:loginform.php?error=".urlencode("Please enter your username"));
            exit();
            //$unameErr = "Please enter username";
        }                   
        else{
            $uname = test_input($_POST["uname"]);
            $uexp = "/^[a-zA-Z]*$/";
            if(!preg_match($uexp,$uname)){
                header("location:loginform.php?error=".urlencode("username should contaion only Alphabetic chars"));
                exit();
            //$unameErr = "only alphabets are allowed"; 
            }
            else $uname = mysqli_real_escape_string($con,$uname);
        }

        if(empty($_POST['pass'])){
            header("location:loginform.php?error=".urlencode("Please enter your password"));
            exit();
            //$passErr = "Please enter password";
        }
        else{
        $pass = test_input($_POST["pass"]);
        $pass = mysqli_real_escape_string($con,$pass);
        }   
    }
    function test_input($data) {
            $data = trim($data);
            $data = stripslashes($data);
            $data = htmlspecialchars($data);
            return $data;
     }
 ?>

  <?php

  $query = "SELECT *FROM user WHERE user.username = ? AND user.password = ?";
  $stmt = mysqli_prepare($con,$query);

  if($stmt){
      mysqli_stmt_bind_param($stmt,'ss',$uname,$pass);
      $run = mysqli_stmt_execute($stmt);

      if($run){
          mysqli_stmt_store_result($stmt);
          $rows = mysqli_stmt_num_rows($stmt);

          if($rows==1){
              $result = mysqli_stmt_get_result($stmt);
              $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
              echo $row['username'];

              //session_start();
              //$_SESSION['uid'] = $row['username'];
              //header('location:welcome.php');
          }
          else{
              header('location:loginform.php?error="Invalid username/password.. Please check and re-try login"');
          }
      }
      else{
          echo "Query Execution Failed";
      }
  }
  else{
      echo "Failed to Prepare Sql Statement";
  }

?>

1 个答案:

答案 0 :(得分:0)

即使您可能找到了解决方案,我也想亲自向您展示(使用您的代码进行测试)。

我首先告诉您,您的问题实际上是您不使用异常处理。如果你这样做了,你会发现你的php / mysqli引发的真正的异常/错误。我建议您始终应用异常处理,至少在您查询数据库时。我将向您介绍封装在完整异常处理代码中的解决方案。如果您需要进一步解释,请随时向我询问。

首先让我们看看你的代码(只是第二个,查询部分是相关的),由我编辑并带入我的表格。

您的代码(容易出错):

<?php

/*
 * Tested on table "user":
 * 
 * ------------------------
 * id  username    password
 * ------------------------
 * 1   John        Smith
 * 2   John        Mark
 */

try {
    // Your received POST values.
    $uname = 'John';
    $pass = 'Smith';

    //---------------------------------------------------------
    // Connect to db.
    //---------------------------------------------------------
    $con = mysqli_connect('<server>', '<user>', '<pass>', '<db>');
    if (!$con) {
        throw new Exception('Connect error:<br/><br/>' . mysqli_connect_errno() . ' - ' . mysqli_connect_error());
    }

    //---------------------------------------------------------
    // Sql statement.
    //---------------------------------------------------------
    $query = "SELECT * FROM user WHERE user.username = ? AND user.password = ?";

    //---------------------------------------------------------
    // Prepare sql statement.
    //---------------------------------------------------------
    $stmt = mysqli_prepare($con, $query);
    if (!$stmt) {
        throw new Exception('The sql statement can not be prepared!');
    }

    //---------------------------------------------------------
    // Binds variables to the prepared statement as parameters.
    //---------------------------------------------------------
    $bound = mysqli_stmt_bind_param($stmt, 'ss', $uname, $pass);
    if (!$bound) {
        throw new Exception('The variables could not be bound to the prepared statement!');
    }

    //---------------------------------------------------------
    // Execute the prepared statement.
    //---------------------------------------------------------
    $executed = mysqli_stmt_execute($stmt);
    if (!$executed) {
        throw new Exception('The prepared statement could not be executed!');
    }

    //---------------------------------------------------------
    // Transfers the result set from the prepared statement.
    //---------------------------------------------------------
    $stored = mysqli_stmt_store_result($stmt);
    if (!$stored) {
        throw new Exception('The result set from the prepared statement could not be transfered!');
    }

    //---------------------------------------------------------
    // Get the number of rows in statements result set.
    //---------------------------------------------------------
    $rows = mysqli_stmt_num_rows($stmt);

    if ($rows == 1) {
        //---------------------------------------------------------
        // Get the result set from the prepared statement.
        //---------------------------------------------------------
        $result = mysqli_stmt_get_result($stmt);
        if (!$result) {
            throw new Exception(mysqli_error($con));

            //----------------------------------------------------------------
            // OR:
            //----------------------------------------------------------------
            // Get a list of errors from the last command executed.
            // Each error displayed as an associative array containing the 
            // errno, error, and sqlstate.
            // Because array returned, then no exception thrown, just display.
            //----------------------------------------------------------------
            // $errorList = mysqli_error_list($con);
            // echo '<pre>' . 'Error retrieving result set:<br/></br>' . print_r($errorList, true) . '</pre>';
            // exit();
            //----------------------------------------------------------------
        }

        //---------------------------------------------------------
        // Read the result set.
        //---------------------------------------------------------
        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
        if (!isset($row)) {
            echo 'No records returned!';
            exit();
        }

        echo 'Returned username is: ' . $row['username'];
    } else {
        echo 'Invalid username/password. Please check and retry login';
    }


    //-----------------------------------------------------------
    // Frees stored result memory for the given statement handle.
    //-----------------------------------------------------------
    mysqli_stmt_free_result($stmt);

    //---------------------------------------------------------
    // Close db connection.
    //---------------------------------------------------------
    $closed = mysqli_close($con);
    if (!$closed) {
        throw new Exception('The database connection can not be closed!');
    }
} catch (Exception $exception) {
    echo '<pre>' . print_r($exception, true) . '</pre>';
    exit();
}

如果您使用 mysqli_stmt_store_result() mysqli_stmt_get_result() 运行此代码,您将获得

错误:

Exception Object
(
    [message:protected] => Commands out of sync; you can't run this command now
    [string:Exception:private] => 
    [code:protected] => 0
    [file:protected] => [...]/index.php
    [line:protected] => 63
    [trace:Exception:private] => Array
        (
        )

    [previous:Exception:private] => 
    [xdebug_message] => ( ! ) Exception: Commands out of sync; you can't run this command now in [...]/index.php on line 63
Call Stack
#TimeMemoryFunctionLocation
10.2170368808{main}(  ).../index.php:0

)

或者以这种形式(参见我的代码):

Error retrieving result set:

Array
(
    [0] => Array
        (
            [errno] => 2014
            [sqlstate] => HY000
            [error] => Commands out of sync; you can't run this command now
        )

)

此异常( Commands out of sync; you can't run this command now )指出,您无法同时运行两个查询。有关详细信息,请参阅this answer,例如。

您在问题中显示的警告实际上告诉您效果:您没有从通话中获得任何mysqli_result

$result = mysqli_stmt_get_result($stmt);

因此你的

$row = mysqli_fetch_array($result, MYSQLI_ASSOC);

接收 FALSE 作为参数($result)并向您发出警告

  

警告:mysqli_fetch_array()期望参数1为mysqli_result,   给出的布尔值   E:\ XAMPP \ htdocs中\ JQ \ login_system_sql_injection_proof \ loginprocess.php   在第57行

为了解决这个问题,我将给你两个解决方案。

解决方案1:

仅使用 mysqli_stmt_get_result() mysqli_fetch_array()

<?php

/*
 * Tested on table "user":
 * 
 * ------------------------
 * id  username    password
 * ------------------------
 * 1   John        Smith
 * 2   John        Mark
 */

try {
    $uname = 'John';
    $pass = 'Smith';

    //---------------------------------------------------------
    // Connect to db.
    //---------------------------------------------------------
    $con = mysqli_connect('<server>', '<user>', '<pass>', '<db>');
    if (!$con) {
        throw new Exception('Connect error:<br/><br/>' . mysqli_connect_errno() . ' - ' . mysqli_connect_error());
    }

    //---------------------------------------------------------
    // Sql statement.
    //---------------------------------------------------------
    $query = "SELECT * FROM user WHERE user.username = ? AND user.password = ?";

    //---------------------------------------------------------
    // Prepare sql statement.
    //---------------------------------------------------------
    $stmt = mysqli_prepare($con, $query);
    if (!$stmt) {
        throw new Exception('The sql statement can not be prepared!');
    }

    //---------------------------------------------------------
    // Binds variables to the prepared statement as parameters.
    //---------------------------------------------------------
    $bound = mysqli_stmt_bind_param($stmt, 'ss', $uname, $pass);
    if (!$bound) {
        throw new Exception('The variables could not be bound to the prepared statement!');
    }

    //---------------------------------------------------------
    // Execute the prepared statement.
    //---------------------------------------------------------
    $executed = mysqli_stmt_execute($stmt);
    if (!$executed) {
        throw new Exception('The prepared statement could not be executed!');
    }

    //---------------------------------------------------------
    // Get the result set from the prepared statement.
    //---------------------------------------------------------
    $result = mysqli_stmt_get_result($stmt);
    if (!$result) {
        throw new Exception(mysqli_error($con));
    }

    //---------------------------------------------------------
    // Get the number of rows in statements result set.
    //---------------------------------------------------------
    $rows = mysqli_num_rows($result);

    if ($rows == 1) {
        //---------------------------------------------------------
        // Read the result set.
        //---------------------------------------------------------
        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
        if (!isset($row)) {
            echo 'No records returned!';
            exit();
        }

        echo 'Returned username is: ' . $row['username'];
    } else {
        echo 'Invalid username/password. Please check and retry login';
    }


    //-----------------------------------------------------------
    // Frees stored result memory for the given statement handle.
    //-----------------------------------------------------------
    mysqli_stmt_free_result($stmt);

    //---------------------------------------------------------
    // Close db connection.
    //---------------------------------------------------------
    $closed = mysqli_close($con);
    if (!$closed) {
        throw new Exception('The database connection can not be closed!');
    }
} catch (Exception $exception) {
    echo '<pre>' . print_r($exception, true) . '</pre>';
    exit();
}

解决方案2:

mysqli_stmt_store_result() mysqli_stmt_bind_result() mysqli_stmt_fetch() 一起使用

<?php

/*
 * Tested on table "user":
 * 
 * ------------------------
 * id  username    password
 * ------------------------
 * 1   John        Smith
 * 2   John        Mark
 */

try {
    $uname = 'John';
    $pass = 'Smith';

    //---------------------------------------------------------
    // Connect to db.
    //---------------------------------------------------------
    $con = mysqli_connect('<server>', '<user>', '<pass>', '<db>');
    if (!$con) {
        throw new Exception('Connect error:<br/><br/>' . mysqli_connect_errno() . ' - ' . mysqli_connect_error());
    }

    //---------------------------------------------------------
    // Sql statement.
    //---------------------------------------------------------
    $query = "SELECT * FROM user WHERE user.username = ? AND user.password = ?";

    //---------------------------------------------------------
    // Prepare sql statement.
    //---------------------------------------------------------
    $stmt = mysqli_prepare($con, $query);
    if (!$stmt) {
        throw new Exception('The sql statement can not be prepared!');
    }

    //---------------------------------------------------------
    // Binds variables to the prepared statement as parameters.
    //---------------------------------------------------------
    $bound = mysqli_stmt_bind_param($stmt, 'ss', $uname, $pass);
    if (!$bound) {
        throw new Exception('The variables could not be bound to the prepared statement!');
    }

    //---------------------------------------------------------
    // Execute the prepared statement.
    //---------------------------------------------------------
    $executed = mysqli_stmt_execute($stmt);
    if (!$executed) {
        throw new Exception('The prepared statement could not be executed!');
    }

    //---------------------------------------------------------
    // Transfers the result set from the prepared statement.
    //---------------------------------------------------------
    $stored = mysqli_stmt_store_result($stmt);
    if (!$stored) {
        throw new Exception('The result set from the prepared statement could not be transfered!');
    }

    //---------------------------------------------------------
    // Get the number of rows in statements result set.
    //---------------------------------------------------------
    $rows = mysqli_stmt_num_rows($stmt);

    if ($rows == 1) {
        //---------------------------------------------------------
        // Bind result set columns to variables.
        //---------------------------------------------------------
        $bound = mysqli_stmt_bind_result($stmt, $resId, $resUsername, $resPassword);
        if (!$bound) {
            throw new Exception('The result set columns could not be bound to the variables');
        }

        //--------------------------------------------------------------------
        // Fetch results from the prepared statement into the bound variables.
        //--------------------------------------------------------------------
        while (mysqli_stmt_fetch($stmt)) {
            echo 'Successfully returned data:<br/><br/>';
            echo 'ID is: ' . $resId . '<br/>';
            echo 'Username is: ' . $resUsername . '<br/>';
            echo 'Password is: ' . $resPassword . '<br/>';
        }
    } else {
        echo 'Invalid username/password. Please check and retry login';
    }

    //-----------------------------------------------------------
    // Frees stored result memory for the given statement handle.
    //-----------------------------------------------------------
    mysqli_stmt_free_result($stmt);

    //---------------------------------------------------------
    // Close db connection.
    //---------------------------------------------------------
    $closed = mysqli_close($con);
    if (!$closed) {
        throw new Exception('The database connection can not be closed!');
    }
} catch (Exception $exception) {
    echo '<pre>' . print_r($exception, true) . '</pre>';
    exit();
}

除了代码之外,我还添加了异常处理和mysqli_stmt_free_result($stmt)函数来释放结果集占用的内存。

祝你好运。