【问题标题】:The apostrophe and backslash paradox撇号和反斜杠悖论
【发布时间】:2014-02-15 04:07:26
【问题描述】:

我一直对此感到困惑,终于屈服于在这里寻求帮助。

我有一个用于抓取的 preg_match 脚本,它在一个循环中匹配不同的变量并将它们存储在一个数组中,最终发布到一个 SQL 表中。只要变量包含撇号,就会出现问题。

这是我获取和组织数据的方式

for($i = 0; $i < count($bokse[0]); $i++){
    preg_match_all("/title=\"Mere information om (.+?)\"/sim", $bokse[0][$i], $name, PREG_SET_ORDER);
    $laeger[$i]['navn'] = stripslashes(mysql_real_escape_string($name[0][1]));
}

现在,我抓取的 mysql_escaped 和 stripped 的值可以是:

**Michael D'Angelo** [NOTICE THE APOSTROPHE]

如果我想将此回显到页面,我可以成功地正确回显D'angelo(带撇号)

echo $laeger[$i]['navn'];

会给我Michael D'Angelo

但是在将其存储在数据库中时,我遇到了一个悖论;我可以选择将其存储为Michael D\'Angelo

或者存储 D,然后收到 SQL 错误。

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'angelo'
(..........blablabv...............)

这是我存储数据的方式

mysql_query("INSERT INTO table (name) VALUES ('".$laeger[$i]['navn']."'")");  or die(mysql_error());

根据我是否使用stripslashes,我要么弄乱查询,要么弄乱结果(使用 bachflash)。 FML。

【问题讨论】:

  • stripslashes 撤销 mysql_real_escape_string 所做的。这就是为什么输出未转义并且以后不适合 SQL 字符串上下文的原因。
  • 我认为你不明白什么是悖论。

标签: php mysql sql regex


【解决方案1】:

没有悖论。你只是不明白转义是如何工作的。

如果你有:

INSERT INTO sometable (fieldname) VALUES ('Michael D\'Angelo')

反斜杠不会进入数据库的磁盘存储。它被数据库的 SQL 解析器剥离。同样,当您从表中检索名称时,它不会被转义。您将收到 Michael D'Angelo 返回给您的客户。

您所拥有的是一个 SQL 注入攻击漏洞 - 允许包含 SQL 元字符的原始用户提供的数据出现在 SQL 上下文中,而无需考虑这些元字符。

这就是为什么有(对于老式代码)像 mysql_real_escape_string() 这样的东西,它会转义提供的字符串中的所有 SQL 元字符,因此它们变成纯文本,不再是“元”。

【讨论】:

  • 那么最合理的解决方案是什么?我对转义没有转化为回声感到有些困惑。
  • 把逃跑当作包装礼物。包装防止礼物被“看到”,直到它到达接收者。一旦完成,它就会被打开并使用。包装被用户扔掉。所以Michael D\'Angelo 被数据库“包装”了。它将Michael D'Angelo 解包并存储在实际数据文件中。一旦 ' 实际存储在数据库中,它就不能再“破坏”查询语句,因为数据库知道它是字符串的一部分,而不是 sql 元字符。
【解决方案2】:

正如您在评论中指出的那样,接受的答案对您没有任何作用。只有事先知道要抓取哪些数据,这样才能将反斜杠放在正确的位置,它才会起作用,但当然,您事先并不知道,因此您需要一个可以在运行时工作的解决方案。 MySQL 为您提供了这样的解决方案。

解决您的问题的答案是将您的插入更改为:

mysql_query("INSERT INTO table (name) VALUES ('".mysql_real_escape_string($laeger[$i]['navn'])."'")");

或者我更喜欢这样做,即使它是非标准的:

 mysql_query("INSERT INTO table set name='".mysql_real_escape_string($laeger[$i]['navn'])."'");

我认为它更容易编码,也更容易阅读。

在我自己的工作中,我创建了一个名为“dbstring”的“辅助函数”,它将撇号包裹在转义函数周围,这使得所有内容更加紧凑、更具可读性、可在数据库之间传输,并且可以抵抗 SQL 注入攻击。

【讨论】:

  • 或者可能是参数化查询?
猜你喜欢
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 2019-12-05
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多