将变量where子句添加到此更新函数的正确方法是什么

时间:2014-05-01 20:01:06

标签: php mysqli where-clause

我在php中创建了一个数据库类。现在我正在测试更新功能。它会返回语法错误或未知列错误,具体取决于where子句的形成方式。

我试过了:

'woord = \'uiteindelijk\'' and 'woord = \"uiteindelijk\"' and 
'woord = "uiteindelijk"' and more

我还在de函数查询中尝试了不同的引号和后缀,但它给了我相同的错误。

我的问题是,如果可能的话,形成where子句的正确方法是什么。如果没有,我该怎么办呢。

database.mysqli.php的一部分

<?php

class myDB {

    private $mysqli;

    public function __construct() {
        require_once('config.php');

        $this->mysqli = new mysqli(HOST, USERNAME, PASSWORD, DB_NAME);  
        if (mysqli_connect_errno()) {
            printf("Connect failed: %s\n", mysqli_connect_error());
        exit();
        }
    }

    public function close() {
        $this->mysqli->close(); 
    }

    private function check($input) {
        if(is_string($input)) {
            $input = trim($input);
            return $this->mysqli->real_escape_string($input);   
        }       
        elseif(is_int($input)) {
            return $input;
        }
        elseif($input === true || $input === false) {
            return $input;
        }
        else {
            die('invalid input');
        }   
    }
    public function update($table, $data, $where) {
        $table = $this->check($table);
        $where = $this->check($where);
        $result = '';
        if (is_array($data)) {
            $update = array();
            foreach ($data as $key => $val) {
                $key = $this->check($key);
                $val = $this->check($val);  
                $update[] .= $key . '=\'' . $val . '\'';
            }
            $query = 'UPDATE ' . $table . ' SET ' . implode(',', $update) . ' WHERE ' . $where;
            if($this->mysqli->query($query)) {
                $result = 'Last updated row id is: '.$this->mysqli->insert_id;
            } 
            else {
                $result = $this->mysqli->error;
            }
        }   
        return $result;
    }

test.php的

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>  

<?php
require_once('database.mysqli.php');
$db = new myDB;
$data = array('woord' => 'gewoontjes', 'lengte' => 10);
$result = $db->update('galgje', $data, 'woord = \'uiteindelijk\'');
echo $result;
$db->close();
?>

</body>
</html>

1 个答案:

答案 0 :(得分:1)

问题来自check方法中的escape_string。此函数用于转义语句中的精确部分,不能以通用方式将其作为整体应用于where子句。

如果您确定您的输入是安全的(不包含破坏sql语句的特殊字符,不管是否恶意),那么只需删除转义。

或者如果您认为它们可能包含特殊字符,出于好的理由或者可能拖动sql注入,那么您必须提供一个更受约束的接口,以便您可以使用适当的转义自行构建where子句。例如:

public function update($table, $data, $woord) {
    ...
    $where = 'woord = \'' . $this->check($woord) . '\'';
    ...
}

编辑:我知道这可能听起来太受限制,但安全性需要付出代价。对于更灵活的东西,您可以查看准备好的语句。它们允许您使用占位符,例如WHERE woord = ? AND id < ?,您可以使用以下内容绑定到变量:

$stmt->bind_param('si', $woord, $id); // 'si' -> 1:string, 2:integer

在这种情况下,mysqli在绑定字符串上应用转义internaly,因此您不必担心它。

请注意,您不能使用占位符来替换整个where子句。 WHERE ? $stmt->bind_param('s', $where);

最后,PDO是用PHP访问数据库的另一种API,支持命名占位符(WHERE woord = :woord而不是WHERE woord = ?)。