我在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>
答案 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 = ?
)。