PHP编写了说明


PHP prepared statements clarification

是否可以在准备好的语句中安全地混合用户输入数据和固定数据,或者每个查询条件都必须有占位符?

例如:

$code = htmlspecialchars($_GET['code']); // USER INPUT DATA
$status = 'A'; // FIXED
$stmt = $connect->prepare("SELECT s_id FROM events WHERE s_code = ? AND s_status = ?") or die(mysqli_error());
$stmt->bind_param('ss', $code, $status);
$stmt->execute();
$stmt->bind_result($reference);

或者这也可以接受吗?

$code = htmlspecialchars($_GET['code']); // USER INPUT DATA
$stmt = $connect->prepare("SELECT s_id FROM events WHERE s_code = ? AND s_status = 'A'") or die(mysqli_error());
$stmt->bind_param('s', $code);
$stmt->execute();
$stmt->bind_result($reference);

这两种方法都是可以接受的。显然,从代码中绑定固定值不会对安全性产生影响,但如果应用程序的各个部分(甚至不同的应用程序)对该查询使用不同的硬编码值,则可能会带来一些性能优势。

为了补充Mureinik提供的答案,您还应该稍微关注用户输入。准备好的语句可以有效地防止SQL注入攻击,但它们并不是针对所有类型攻击的通用解药。

从你的例子来看,我认为$_GET['code']是一个整数。作为一个额外的安全层,您可以(也应该)净化并验证用户输入。大致如下:

// avoid accessing directly super-globals like $_GET, $_POST
// @see Sanitize filters: http://nl1.php.net/manual/en/filter.filters.sanitize.php
$code = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_NUMBER_INT);
// @see Validate filters: http://nl1.php.net/manual/en/filter.filters.validate.php
$options = array(
    'options' => array(
        'min_range' => 1,
        'max_range' => 1000000,
));
if (!filter_var($code, FILTER_VALIDATE_INT, $options)) {
    echo 'Invalid code!';
}