在SQL中转义引号

我对这个话题有点困惑,所以我决定向你们询问一下:) 从php.net开始,我应该使用mysql_real_escape_string()并关闭魔术引号,因为它已被弃用。 所以我关闭了,我使用mysql_real_escape_string(),但这样就足够了吗?:
$value = "It's Time!";
$escaped_value = mysql_real_escape_string($value);

mysql_query("INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")");
当我检查数据库中的数据时,它看起来与$ value相同,所以
"It's Time"
而不是
"It's Time"
,这是正常的,这不应该在引号前添加斜杠吗?     
已邀请:
这是正确的行为,它的工作原理!报价在查询中转义,而不是在数据库中转义。在SQL查询中必须转换为'在数据库内部'。您转义字符串,以便SQL查询不会搞砸,并允许输入引号到数据库,而不会将SQL查询解释为控制字符。 您转义的查询将是:
mysql_query("INSERT INTO table (column, column2) VALUES ('It's time', "0")");
您的数据库数据应该是“它的时间”。 如果它没有被转义,它将是:
mysql_query("INSERT INTO table (column, column2) VALUES ('It's time', "0")");
它将吐出关于“时间”的错误(因为它只会解释到下一个引用字符,并且只会看到'它'。)并且“它是时候了!”只是一个无害的字符串,但如果你不逃避你的角色,很多攻击可能来自于它。     
简短的回答 这是对的。 答案很长 这是正确的,但你的问题表明对这里发生的事情缺乏深入的理解。这是您的查询:
INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")
让我们看看如果你不逃避会发生什么,并且用户输入以下数据:
Eve'
请记住,您只是将字符串传递给MySQL,插入是通过PHP的字符串处理完成的。这意味着在这个实例中,发送到mysql_query的查询是:
INSERT INTO table (column, column2) VALUES ('Eve'', "0")
这是一个语法错误,会导致页面错误。现在,当像我这样的用户(即一个打算让你的一天成为苦难的混蛋:D)发现其中一个时,我们知道是时候玩了。如果用户提供以下数据会发生什么?
Eve', "0"); DROP TABLE table--
我们的查询扩展到:
INSERT INTO table (column, column2) VALUES ('Eve', "0"); DROP TABLE table--', "0")
这不是语法错误,但它有问题......我们现在正在执行一个我们从未打算过的查询! (如果你不认识它,“ - ”表示SQL中的注释,即“忽略此点后的所有内容”)。 现在这不可能在这个确切的实例中发生(mysql_query不支持多个查询),但它是你试图阻止的那种攻击 - 一类称为SQL注入的攻击。让我们看看当你使用mysql_real_escape_string时会发生什么! 输入的数据变为:
Eve', "0"); DROP TABLE table--
这意味着我们的查询字符串如下:
INSERT INTO table (column, column2) VALUES ('Eve', "0"); DROP TABLE table--}', "0")
哪个好!用户输入的数据将在输入数据时存储在数据库中。不是没有引号,也不是有额外的反斜杠,而是在它们进入时。这个很重要。如果以任何其他方式存储数据,您将在以后遇到问题,包括解除转义或双重转义。此外,添加额外的斜杠或类似的东西通常会以某种方式暴露给用户,这是一个巨大的警告信号,表明事情可能无法正常转义。你想避免做错事,你特别想避免做错事并做广告,这将我带到下一部分: 逃避数据的替代方案 魔术引号。如你所述,弃用(并有充分理由),避免。 不要逃避你的数据。我建议不要这个选项。 从输入中删除坏字符。在几乎所有情况下都很烦人,你应该存储用户输入的内容,而不是技术上易于存储的东西。 禁止输入中的错误字符。有时可以接受(信用卡号码字段不需要处理报价),有时很烦人,有时候是一个巨大的警告标志(例如在密码字段上) 准备好的陈述。我说字符串中的变量“填充”是由PHP完成的,MySQL只是获取一个查询字符串,因此需要转义。准备好的语句通过更加智能化来卸载这项工作,并且使用预准备语句看起来像这样(警告:伪代码): $ statement = $ db-> prepare('INSERT INTO table(column,column2)VALUES(“%1”,“%2”)'); $ result = $ statement-> execute($ value1,$ value2); 关于SQL转义方法有一个很好的StackOverflow问题,那里的答案会更深入,所以你可能想要阅读它。 就个人而言,这是我喜欢的选项。您不能忘记转义变量并以这种方式将其插入数据库 - 要么正确编组了值,要么它们没有到达数据库附近的任何位置,没有中途选项。也就是说,假设您强制执行所有查询都通过预准备语句,并且没有字符串连接
$db->prepare('INSERT INTO table VALUES('.$value.')'))
已经完成了。在我看来,这比跟踪哪些变量被消毒以及哪些不被消毒更容易。有些人喜欢从用户那里获得字符串,但如果他们可以去除数据库以外的任何地方 - 回到HTML,进入内存缓存等等,那就太尴尬了。如果你打算自己做,我可能会建议一些匈牙利表示法,例如:
$uValue = $_POST['value'];
$sValue = escape($uValue);
$db->query('INSERT INTO table VALUES(' . $sValue .')');
我第一次看到这个想法是由Joel Spolsky撰写的一篇优秀文章“让错误的代码看错”。 结论 希望您现在能够更好地准备制作注射防护网站。祝你选择哪种方法好运,并确保在它到达数据库之前总是逃避所有用户输入! ;)     
mysql_real_escape_string()通常足以阻止SQLI。 您还应该过滤从用户获得的数值(通过使用intval())。     

要回复问题请先登录注册