19

我正在处理一个表单,用户可以在要提交到数据库的字符串中使用非法/特殊字符。我想转义/否定字符串中的这些字符并且一直在使用htmlspecialchars()。但是,有没有更好/更快的方法?

4

6 回答 6

30

数据库没有“非法”字符。不能存储某些字符的数据库是无稽之谈。有一些服务字符,如引号,用于分隔字符串。这些字符应该只是被转义,而不是被消除。

要将查询发送到数据库,您有 2 个选项:

  1. 以通常的方式构建查询,使其看起来与您可以在 sql 控制台中运行的 SQL 查询完全相同。
    要做到这一点,应该了解一整套规则,而不仅仅是“使用 mysql_real_escape_string”。
    规则如:

    • 字符串应该用引号括起来并转义。这就是转义的唯一含义:它只是转义分隔符!(以及其他一些字符 - 字符串终止字符和转义字符本身)。没有引号 mysql_real_escape_string 是没用的。
    • 数字应该明确地转换为它的类型。虽然虽然数据编号可以像字符串一样受到威胁,但也有一些数字,如 LIMIT 子句参数,不能转义,只能强制转换。
  2. 分别发送查询和数据。
    这是最优选的方式,因为它可以缩短为“使用绑定”。所有字符串、数字和 LIMIT 参数都可以绑定 - 完全不用担心。
    使用这种方法,您的占位符查询按原样发送到数据库,绑定数据在单独的数据包中发送,因此不会干扰。就像代码数据分离一样。您发送与数据分开的程序(查询本身)。

但!

上面所说的一切仅涵盖查询的数据部分。
但有时我们必须使查询更加动态,添加运算符或标识符。
在这种情况下,每个动态参数都应该在我们的脚本中进行硬编码并从该集合中选择。
例如,要进行动态排序:

$orders  = array("name","price","qty"); //field names
$key     = array_search($_GET['sort'],$orders)); // see if we have such a name
$orderby = $orders[$key]; //if not, first one will be set automatically. smart enuf :)
$query   = "SELECT * FROM `table` ORDER BY $orderby"; //value is safe

或动态搜索:

$w     = array();
$where = '';

if (!empty($_GET['rooms']))     $w[]="rooms='".mesc($_GET['rooms'])."'";
if (!empty($_GET['space']))     $w[]="space='".mesc($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mesc($_GET['max_price'])."'";

if (count($w)) $where="WHERE ".implode(' AND ',$w);
$query="select * from table $where";

在此示例中,我们仅将用户输入的数据添加到查询中,而不是字段名称,这些都是在脚本中硬编码的。对于绑定,算法将非常相似。

等等。

于 2010-06-08T06:15:55.473 回答
13

如果您将此数据提交到数据库,请查看您的数据库的转义函数。

也就是说,对于 MySQL,有mysql_real_escape_string

这些转义函数会处理任何可能是恶意的字符,并且您仍然可以以与放入数据相同的方式获取数据。

您还可以使用准备好的语句来处理数据:

$dbPreparedStatement = $db->prepare('INSERT INTO table (htmlcontent) VALUES (?)');
$dbPreparedStatement->execute(array($yourHtmlData));

或者多一点自我解释:

$dbPreparedStatement = $db->prepare('INSERT INTO table (htmlcontent) VALUES (:htmlcontent)');
$dbPreparedStatement->execute(array(':htmlcontent' => $yourHtmlData));

如果要保存不同类型的数据,请使用bindParam来定义每种类型,即可以通过以下方式定义整数:$db->bindParam(':userId', $userId, PDO::PARAM_INT);。例子:

$dbPreparedStatement = $db->prepare('INSERT INTO table (postId, htmlcontent) VALUES (:postid, :htmlcontent)');
$dbPreparedStatement->bindParam(':postid', $userId, PDO::PARAM_INT);
$dbPreparedStatement->bindParam(':htmlcontent', $yourHtmlData, PDO::PARAM_STR);
$dbPreparedStatement->execute();

$db您的 PHP 数据对象 (PDO)在哪里。如果您不使用它,您可以在PHP Data Objects了解更多信息。

于 2010-06-07T20:53:23.977 回答
2

首先,您应该在显示时对内容进行清理,而不是在插入数据库之前。SQL 注入是另一回事,但可能离题。

其次,如果您根本不需要您的用户能够发布 HTML,这htmlspecialchars就是您所需要的。它负责处理 HTML 中的所有特殊字符。

于 2010-06-07T20:50:22.963 回答
1

我正在处理一个表单,用户可以在要提交到数据库的字符串中使用非法/特殊字符。

用户实际上可以做的远不止这些。

我想转义/否定字符串中的这些字符,并且一直在使用 htmlspecialchars()。但是,我想知道是否有更好/更快的方法。

使用HTML 净化器

HTML Purifier 是一个用 PHP 编写的符合标准的 HTML 过滤器库。HTML Purifier 不仅会使用经过全面审核、安全且许可的白名单删除所有恶意代码(更广为人知的 XSS)。

并自己决定:)

于 2010-06-07T20:48:53.080 回答
0

这不是您想自己解决的问题。有一些库可以为您执行此操作,例如HTML Purifier

于 2010-06-07T20:49:48.507 回答
0

您尚未说明这些非法字符可能是什么,但您绝对应该使用数据库 API 提供的机制来转义数据。例如,如果您使用 MySQL,请使用 PDO 参数化 SQL 语句。

于 2010-06-07T20:51:58.737 回答