当前位置: 首页 > 面试题库 >

将准备好的语句包装在函数中

孙梓
2023-03-14
问题内容

我一直在阅读有关SQL注入的文章,并决定修改我的代码以防止SQL注入。

例如,我有一个输入,将值插入到数据库中。最初,我的预防注射措施是:

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    // $data = addslashes($data);
    $data = mysql_real_escape_string($data);
    return $data;
}

$artist = $_POST["artist"];     // can be anything
$artist = test_input($artist);  // escaped chars are &, quotes, <, >, \n, \r, etc.

if ($mysqli->query("SELECT * FROM `my_table` WHERE `artist` = '$artist'")->num_rows == 0) {
    $mysqli->query("INSERT INTO my_table (artist) VALUES ('$artist')");
    echo "New artist is added.";
} else {
    echo "Artist already exists.";
}

在我读过的文章中,有人建议应该使用准备好的语句。我已经更改了代码并使用了它:

$artist = $_POST["artist"]; // can be anything

$query = $mysqli->prepare("SELECT * FROM my_table WHERE artist = ?");
$query->bind_param("s", $artist);
$query->execute();
$result = $query->get_result();
$query->close();

if ($result->num_rows == 0) {
    echo "Artist doesn't exist in the DB." . PHP_EOL;
    $query = $mysqli->prepare("INSERT INTO my_table (artist) VALUES (?)");
    $query->bind_param("s", $artist);
    $query->execute();
    if ($query->affected_rows > 0) {
        echo "Artist is added to the DB." . PHP_EOL;
    }
    $query->close();
} else {
    echo "Artist already exists in the DB." . PHP_EOL;
}

尽管这可以防止SQL注入,但是它对XSS并没有任何作用。因此,我决定修改test_input(removed $data = mysql_real_escape_string($data);)并使用它来防止脚本注入。

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

$artist = $_POST["artist"]; // can be anything
$artist = test_input($artist);

现在,我的问题是关于使用准备好的语句。我将插入三个项目;艺术家,专辑和歌曲。一遍又一遍地重复相同的过程(准备,绑定,执行,关闭)对我来说似乎是多余的。我想创建一个函数,并用它包装准备好的语句过程。像这样的东西:

function p_statement($mysqli, $query_string = "", $type = "", $vars = []) {
    $query = $mysqli->prepare($query_string);
    $query->bind_param($type, $vars);
    $query->execute();
    $result = null;
    preg_match("/^[A-Z]+/", $query_string, $command);
    switch ($command[0]) {
        case "SELECT":
            $result = $query->get_result();
            break;
        case "INSERT":
            $result = $query->affected_rows;
            break;
    }
    $query->close();
    return $result;
}

但是,这带来了一个问题:$vars数组。由于要传递给变量的数量mysqli_stmt::bind_param()是可变的/动态的,因此我在main函数中使用了一个数组p_statement。我不知道如何将数组中的项目传递给mysqli_stmt::bind_param()bind_param期望(type, var1, var2, varn,),并且我有一个数组。

我该如何进行这项工作?


问题答案:

您正在寻找 implode()

查看联机帮助页,它显示了有关使用的信息call_user_func_array。我编辑了您的一些片段。

function p_statement($mysqli, $query_string = "", $type = "", $vars = []) {

    $query = $mysqli->prepare($query_string);

    //assign $type to first index of $vars
    array_unshift($vars, $type);

    //Turn all values into reference since call_user_func_array
    //expects arguments of bind_param to be references
    //@see mysqli::bind_param() manpage
    foreach ($vars as $key => $value) {
        $vars[$key] =& $vars[$key];
    }

    call_user_func_array(array($query, 'bind_param'), $vars);
    $query->execute();

    //INSERT, SELECT, UPDATE and DELETE have each 6 chars, you can
    //validate it using substr() below for better and faster performance
    if (strtolower(substr($query_string, 0, 6)) == "select") {
        $result = $query->get_result();
    } else {
        $result = $query->affected_rows;
    }

    $query->close();
    return $result;
}


 类似资料:
  • 我一直在阅读有关SQL注入的文章,并决定修改我的代码以防止SQL注入。 例如,我有一个输入,我将值插入到我的数据库中。最初,我对注射的警惕是这样的: 在我读过的文章中,有人建议应该使用预准备语句。我更改了我的代码并使用了它: 虽然这可以防止SQL注入,但它不会对XSS做任何事情。所以我决定修改(并使用它来防止脚本注入。 现在,我的问题是如何使用预先准备好的语句。我将插入三个项目;艺术家、专辑和歌曲

  • 我有以下准备的一个准备好的声明失败了... 我在我的第一份准备好的声明中几乎有同样的准备,而且它进行得很好。我不确定是否我有两个准备好的声明,如果这是造成一个问题,或情况可能是什么? 现在我有个错误... 更新-可能的内部连接,像这样?

  • 问题内容: 我一直在做的简单连接,: 虽然使用这个我一直使用的简单的方法,使查询之前逃脱的任何数据,不管是,,或者通过使用 现在我知道这在一定程度上是安全的! 它逃脱了危险人物;但是,它仍然容易受到其他攻击的攻击,这些攻击可能包含安全字符,但可能有害于显示数据或在某些情况下恶意修改或删除数据。 因此,我进行了一些搜索,以了解有关PDO,MySQLi和准备好的语句的信息。是的,我可能迟到了游戏,但是

  • 问题内容: 我刚刚开始做我的第一个项目(很有趣)。我正在学习PHP和MySQL,并且已经完成了我的第一个正常工作的应用程序。它可以工作,但是我现在正在学习如何保护应用程序的安全,从而防止SQL注入。我大约有50多个PHP文件来管理与MySQL数据库的交互。它们看起来都是这样的: 这是我在整个应用程序中用于向数据库读写数据的格式。如果我需要将它们更改为准备好的语句,而不是在其中插入任何信息,而只是在

  • 场景:继我之前的问题(在存储过程中使用游标循环行MySQL)之后,我尝试执行一个嵌套的prepare语句,在该语句中,我向外部语句输入一个日期,然后调用内部语句,该语句从表中获取数据。 代码: 问题:这段代码运行时没有错误,但没有给出任何结果。如果我只运行第一个准备好的语句,一个接一个地直接输入变量,就可以了。所以我猜问题在于我的第二句话。 问题:你知道我做错了什么吗? Obs:第二个代码应该循环