我听过有人说(关于C#/ SQL Server,但也与PHP / MySql有关):不要手动转义字符串 - 改为使用存储过程。
好的,我可以接受这个建议,但为什么呢?许多人说(包括在SO上)mysql_real_escape_string()
已经足够了,mysql_real_escape_string()
很好,mysql_real_escape_string()
是第一种保护方式。
为什么呢?是否存在mysql_real_escape_string()
失败的情况?至少一个......我不需要很多:)
答案 0 :(得分:9)
当mysql_real_escape_string 失败:
时$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']);
如果$_GET['user_id']
设置为 1或1 = 1 ,则没有特殊字符且未过滤。
结果:返回所有行。
情况变得更糟。怎么样......如果$_GET['user_id']
设置为 1或is_admin = 1 怎么办?
该功能仅用于单引号内时使用。
答案 1 :(得分:1)
仅供参考:
mysql_real_escape_string()
无法逃脱%
和_
。如果与LIKE, GRANT, or REVOKE
结合使用,这些是MySQL中的通配符。
答案 2 :(得分:0)
mysql_real_escape_string()
可能会失败来清理输入。
由于mysql_real_esacpe_string()
在清理字符串时会考虑字符集。
有问题。您可以通过发送查询的mysql_query
函数更改字符以更改连接的字符集。但是,mysql_real_escape_string()
无视您正在使用的集合,并且它会不正确地逃避某些字符。
另一件事是不断手动调用它。即使将它包装在一个函数中也是P.I.T.A.因为它意味着您必须创建自己的某种数据库包装/数据库抽象层,以便能够自动调用mysql_real_escape_string()
。
这就是为什么我们在PHP中使用PDO可以帮助我们减轻上述所有内容,并且您可以使用参数化的预处理语句 处理重复查询以改变数据的优选方式。
准备语句,绑定输入变量,它将根据正在使用的数据库驱动程序和连接的字符集清除输入。它的代码更少,更安全。
答案 3 :(得分:0)
mysql_real_escape_string()和SQL Injection只有一件事 -
前者与后者没有丝毫关系。
虽然这听起来很自相矛盾,但没有比这更真实了。
这是证明它的两个陈述
因此,在适用的情况下,无论如何都必须使用此功能,尽管存在任何危险或恐惧。在任何其他情况下,它都没有任何帮助。
我唯一需要补充的是,预备语句也不能提供全面保护。以下是解释和建议:https://stackoverflow.com/a/8255054/285587