在PHP中,当我向数据库提交字符串时,我应该使用htmlspecialchars()处理非法字符还是使用正则表达式?

Bro*_*ias 19 php sql-injection special-characters illegal-characters

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

You*_*nse 31

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

要向数据库发送查询,您有两个选择:

  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
Run Code Online (Sandbox Code Playgroud)

或动态搜索:

$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";
Run Code Online (Sandbox Code Playgroud)

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

等等.

  • 谢谢,这真的很有帮助. (2认同)

fav*_*avo 14

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

也就是说,MySQL有mysql_real_escape_string.

These escape functions take care of any characters that might be malicious, and you will still get your data in the same way you put it in there.

You can also use prepared statements to take care of the data:

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

Or a little more self explaining:

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

In case you want to save different types of data, use bindParam to define each type, that is, an integer can be defined by: $db->bindParam(':userId', $userId, PDO::PARAM_INT);. Example:

$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();
Run Code Online (Sandbox Code Playgroud)

Where $db is your PHP data object (PDO). If you're not using one, you might learn more about it at PHP Data Objects.

  • SQL注入问题的更好解决方案是使用参数化查询.这摆脱了完全用手逃脱的需要. (6认同)
  • 是参数化查询.为什么要引导人们使用更容易注射的旧技术? (2认同)