当字符串包含单引号时 PHP preg_replace() 返回 null 但否则有效

Posted

技术标签:

【中文标题】当字符串包含单引号时 PHP preg_replace() 返回 null 但否则有效【英文标题】:PHP preg_replace() is returning null when string includes a single quote but works otherwise 【发布时间】:2019-02-07 11:00:05 【问题描述】:

下面的代码很简单。 php 使用 POST 从表单中收集字符串,然后我希望对其进行修剪并运行 preg_replace 函数,该函数将去除除单引号或连字符之外的任何特殊字符。请记住,整个代码可以正常工作,而无需在正则表达式中使用引号或连字符。

preg_replace("/[^\w\s'-]/", '', $raw_lemurName);

然后将这些干净的变量插入数据库。阿帕奇/2.4.37。 MariaDB。

当我将 lemurName 设为“Diademed Sifaka!”之类的字符串时,它会起作用,并返回 'Diademed Sifaka'。

但是,当我将其设为包含单引号的字符串时,例如“Coquerel's Sifaka”,操作未完成且未插入任何信息。

我已经单独测试了正则表达式,它工作正常,似乎当你开始涉及 SQL 和数据库时,它就停止工作了。

值得注意的是:

使用 phpMyAdmin。如果我在其中插入字符串,它可以正常工作,因此我的数据库可以保存这些值。 尝试在各个地方使用 mysqli_real_escape_string(),但没有成功,可能是做错了。 仔细阅读,我认为这与 SQL 不允许插入带有单引号的字符串以及服务器在 post 方法中自动转义单引号有关。

有什么想法吗?

非常感谢。

$raw_lemurName          =    isset($_POST['lemurName']) ? $_POST['lemurName'] : null;

$raw_lemurLat           =    isset($_POST['lemurLat']) ? $_POST['lemurLat'] : null;

$raw_family             =    isset($_POST['family']) ? $_POST['family'] : null;

//下面的正则表达式似乎搞砸了

$c_lemurName            =    trim(preg_replace("/[^\w\s'-]/", '', $raw_lemurName));

$c_lemurLat             =    strtolower(trim(preg_replace('/[^\w\s]/', '', $raw_lemurLat))); 

$c_family               =    trim(preg_replace('/[^\w\s]/', '', $raw_family));

if (isset($_POST['submit'])) 

$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";

$run_query = mysqli_query($connection, $query1);

if($run_query)
    echo "Data has been inserted";

 else 
    echo "Operation Unsuccessful";


    header("location:  index.php");

    return;

【问题讨论】:

【参考方案1】:

这是一个标准的 SQL 注入问题。问题源于您将这些变量纳入查询的方式:

$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";

想想这里到底发生了什么,你所做的只是将字符串连接在一起,所以如果$c_lemurName' - 那么你的SQL 将变成:

[...] VALUES (NULL, ''', '[...]

这实际上让您了解所谓的“注入攻击”。基本上,恶意用户可以将$c_family 设置为... ');drop table lemurs;-- - 您现在正在执行插入语句,然后是删除表语句,其余的SQL 是注释。

有几种方法可以解决这个问题,最常见的建议方法是查看参数化查询——对于 mysqli 库来说,这必须通过准备好的语句来完成。 PHP docs page 上有一个例子。

【讨论】:

使用了参数化查询,效果很好。干杯。【参考方案2】:

也替换第二个参数区域的单引号。用这个。

preg_replace("/[^\w\s'-]/", "", $raw_lemurName);

希望它会起作用

【讨论】:

以上是关于当字符串包含单引号时 PHP preg_replace() 返回 null 但否则有效的主要内容,如果未能解决你的问题,请参考以下文章

当变量包含单引号时 SQL 动态查询字符串中断

如何插入包含单引号的字符串

php单引号中可以包含双引号吗

php 笔记 2016/7/5

有关PHP的字符串知识

PHP 字符串