在PHP和MySQLi中使用Use prepared语句和参数化查询

时间:2018-03-28 23:07:26

标签: php mysqli

我正在学习如何在我的简单登录系统中使用预准备语句,以使其更安全。

我已经按照一些不同的教程来使其工作,但无法让它工作。当我输入错误的用户名和密码时,它会给我错误。当我输入用户名和密码正确时,我仍然会收到错误。

我做错了什么?

我是新手,对任何明显的错误表示道歉。

我还调查了哈希密码,因为它目前在数据库中以纯文本形式存储,但这是我完成此工作后的下一步。

这是我的代码:

<?php

error_reporting(E_ALL); ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message

if($SERVER['REQUESTMETHOD'] == 'POST') {
if (empty($POST['username']) || empty($POST['password'])) {

$error = "Enter Username and Password";

}

else
{
// Define $username and $password
$username = $_POST['username'];
$password = $_POST['password'];

//connect to database
include('dbconx.php');

}

$stmt = $con->prepare("SELECT * from admin where password=? AND username=?");
$stmt->bind_param('ss', $username, $password); 
$stmt->execute();
$stmt->bind_result($id, $username, $password);
$stmt->store_result();
if($stmt->num_rows == 1) //To check if the row exists
{

        $_SESSION['login_user'] = $username; // Initializing Session
        header("location: confirm.php"); // Redirecting To Other Page

    }
else {
$error = "Username or Password is incorrect";
}

mysqli_close($con); // Closing Connection
}

?>

3 个答案:

答案 0 :(得分:2)

您有向后绑定的参数参数。您的查询会将ALTER PROCEDURE [dbo].[spSearchWord] @Word nvarchar(100) AS BEGIN SET NOCOUNT ON; SELECT * FROM [testDatabase].[dbo].[User] WHERE CONTAINS (*, @Word) END password绑定,但您的username会使用bind_param(),然后使用$username

我从来不喜欢使用返回的行数来确定存在。相反,您只需使用$password即可。它将返回一个布尔值,指示是否有结果。

例如

fetch()

答案 1 :(得分:-1)

应在mysqli_stmt::store_result之前调用

mysqli_stmt::bind_result,同时您需要致电mysqli_stmt::seek_datamysqli_stmt::fetch以获取结果。

示例:

<?php

$db = new Mysqli(...);

$inputUsername = $_POST['username'] ?? '';
$inputPassword = $_POST['password'] ?? '';

$statment = $db->prepare('SELECT `id`,`username`,`password` FROM `admin` WHERE `username` = ?');

$statment->bind_param('s',$inputUsername);

$statment->execute();

$statment->store_result();

$statment->bind_result($id,$username,$password);

if($statment->num_rows) {

    $statment->data_seek(0);
    $statment->fetch();

    /**
    * this is not secure
    * @see http://php.net/manual/en/function.password-hash.php
    */
    if($inputPassword === $password) {
        echo sprintf('Welcome, %s!',$username);
    } else {
        echo 'Incorrect password!';
    }

} else {

    echo sprintf('No such user with the given username (%s)',$inputUsername);

}

$statment->close();
$db->close();

答案 2 :(得分:-1)

bind_resultstore_result删除了get_resultfetch_assoc。它使得db记录更加灵活和稳定。

重定向后还添加了exit();,因此重定向命令后不会执行其他代码。

错字:

if (empty($POST['username']) || empty($POST['password']))

  • ^ $POST应该是$_POST
如果为空,则未正确检查

$error。即使出现错误,仍会经过mysqli functions阻止。修复了通过创建包含if statement块的适当mysqli funtions的问题。

还为代码添加了适当的缩进以便于阅读。

新代码:

<?php
error_reporting(E_ALL); 
ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message

$_POST['username'] = isset( $_POST['username'] ) ? $_POST['username'] : '';
$_POST['password'] = isset( $_POST['password'] ) ? $_POST['password'] : '';

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    if (empty($_POST['username']) || empty($_POST['password'])) {
        $error = "Enter Username and Password";
    }
    else{
        // Define $username and $password
        $username = $_POST['username'];
        $password = $_POST['password'];

        //connect to database
        include('dbconx.php');
    }

    if( $error == "" ) {
        $stmt = $con->prepare("SELECT * from students where username=? AND password=?");
        $stmt->bind_param('ss', $username, $password); 
        $stmt->execute();
        $result = $stmt->get_result();

        if($result->num_rows == 1) {
            $row = $result->fetch_assoc();
            $_SESSION['login_user'] = $row['username']; // Initializing Session
            header("location: confirm.php");exit(); // Redirecting To Other Page
        }
        else {
            $error = "Username or Password is incorrect";
        }

        mysqli_close($con); // Closing Connection
    }
    echo $error;
}

?>