用准备好的陈述?我根本不明白

时间:2013-05-03 12:43:05

标签: php mysql mysqli

我被告知这段代码非常容易受到SQL注入的影响。如何将其更改为安全?我知道使用准备好的陈述是最好的,但我没有找到一种不破坏它的方法。

<?php

$con = new mysqli("localhost", "", "", "");
// Check connection
if (mysqli_connect_errno()) {
    echo "Failed to connect to MySQL: " . mysqli_connect_error();
}

$existsQuery = "select count(*) as count from entry where emailaddress like '" . $_POST[emailaddress] . "'";
$existsResult = mysqli_query($con, $existsQuery);

if ($existsResult->fetch_object()->count > 0) {
    header('Location: index2.php?email=exists');
} else {
    $sql = "INSERT INTO entry (firstname, lastname, emailaddress, favoritesong) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[emailaddress]','$_POST[favoritesong]')";

    if (!mysqli_query($con, $sql)) {
        die('Error: ' . mysqli_error($con));
    }
    echo "1 record added";
}

mysqli_close($con);
?>

2 个答案:

答案 0 :(得分:3)

避免SQL注入的重要一点是,您不使用字符串连接构建查询。

所以不要像这样构建查询......

$sql = "select count(*) from entry where emailaddress like '" . $_POST[emailaddress] . "'";
$sth = $pdo->prepare($sql);
$sth->execute();

...你会改为使用绑定。有了约束力,?占位符将替换为电子邮件地址,但数据库知道如何引用以及如何转义输入...

$sql = 'select count(*) from entry where emailaddress like ?';
$sth = $pdo->prepare($sql);
$sth->bindParam(1, $_POST[emailaddress], PDO::PARAM_STR);
$sth->execute();

此参数化查询在PDO和SQLi中工作。有关SQL注入如何工作的演示,您可以看到here,只需单击下一个箭头即可填写错误的用户输入。

还有一件事需要考虑,绑定会对SQL注入提供一定的保护,但这不应该阻止您验证用户输入。在您的示例中,这意味着您检查输入是否真的是电子邮件地址,否则只是拒绝用户输入。

答案 1 :(得分:0)

您需要转义传递给SQL的所有变量,尤其是所有$ _POST和$ _GET。

恕我直言,您可以使用PDO(引用示例:http://php.net/manual/en/pdo.quote.php)。

我希望有所帮助。