使用mysql / php获取数据的安全方法

时间:2012-08-24 12:17:46

标签: php mysql sql code-injection

在我知道使用预准备语句及其对SQL注入的作用之前,我编写了这段代码。现在我也意识到使用预处理语句获取数组有多乱。所以我想知道这段代码是否可以安全使用,因为它不使用任何用户提交的信息来获取行。

它的作用是使用会话ID识别db表中的行,session_check函数确保会话等。:

$username = $_SESSION['username'];
$select = mysqli_query($link, " SELECT product_id, product_title, product_value                             
                                FROM product
                                WHERE user_id='$username'");

while ($row = mysqli_fetch_assoc($select))
{
    $product[] = array(
            'product_id' => $row['product_id'], 
            'product_title' => $row['product_title'], 
            'product_value' => $row['product_value']);
}

关于这个问题的一些信息真的很值得赞赏,因为事情进展顺利,直到我知道准备好的陈述。

修改
所以,我有点朝另一个方向走,并完全跳过了这个查询的数组部分。相反,我选择了准备好的声明并做了类似的事情......:

$select_stmt = $db->prepare("SELECT etc...)
$select_stmt->bind_param("CODE")
$select_stmt->execute();
等等..

但事实是我的bind_result变得非常大(?)有14个变量。也许这是一个愚蠢的问题,但与使用单个阵列的旧方式相比,这会减慢我的网站(如果14甚至被认为是“大”)?这是一个常见的查询,希望许多用户可以同时使用。准备好的陈述对我来说是新的......

感谢帮助人们的帮助。

2 个答案:

答案 0 :(得分:1)

如果用户名是例如Jean D'arc到达mysql服务器的字符串将是

SELECT
  product_id, product_title, product_value
FROM
  product
WHERE
  user_id='Jean D'arc'

这将导致解析错误 在 sql语句中正确编码/转义参数不仅是防止用户恶意输入所必需的,而且对于你不能(绝对确定)确保它不包含字符的每个参数都是必要的。可能会破坏声明。如果(任何微小的)怀疑编码/转义参数,或只是使用准备好的语句。

答案 1 :(得分:1)

您应该查看准备好的陈述。这是mysqli的众多好处之一。它允许您插入变量而不必担心SQL注入。 mysqli_real_escape_string大部分时间都可以工作,但准备好的语句是避免攻击的唯一真正安全的方法。

来自manual

的示例
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$city = "Amersfoort";

/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) {

    /* bind parameters for markers */
    $stmt->bind_param("s", $city);

    /* execute query */
    $stmt->execute();

    /* bind result variables */
    $stmt->bind_result($district);

    /* fetch value */
    $stmt->fetch();

    printf("%s is in district %s\n", $city, $district);

    /* close statement */
    $stmt->close();
}