在我正在使用的旧服务器上,我无法使用预准备语句,我目前正在尝试完全转义用户输入,然后再将其发送到MySQL。
为此我使用PHP函数mysql_real_escape_string
。
由于此函数不会转义MySQL通配符%和_我也使用addcslashes
来转义这些函数。
当我发送类似的东西时:
test_test " '
到数据库然后读回数据库显示:
test\_test " '
看着这个我无法理解为什么_有一个前面的反斜杠但是'和'没有。 因为它们全部都是\ _ \ _并且“所有都显示相同,即所有都有可见的转义字符或者都没有可见。
是否会自动屏蔽转义
任何人都能解释一下吗?
答案 0 :(得分:87)
_
和%
一般不是MySQL中的通配符,不应为了将它们放入普通的字符串文字而进行转义。 mysql_real_escape_string
对于此目的是正确和充分的。不应使用addcslashes
。
_
和%
仅在LIKE
- 匹配的上下文中有特殊之处。如果要在LIKE
语句中准备文字字符串使用,以便100%
匹配百分之百而不仅仅是以百分之一开头的任何字符串,那么您有两个级别的转义需要担心
首先是LIKE逃避。 LIKE处理完全在SQL内部进行,如果要将文字字符串转换为文字LIKE表达式,即使使用参数化查询,也必须执行此步骤!
在此计划中,_
和%
是特殊的,必须进行转义。转义字符也必须转义。根据ANSI SQL,除了之外的字符不得转义:\'
是错误的。 (虽然MySQL通常会让你逃脱它。)
完成此操作后,您将进入第二级转义,这是简单的旧字符串文字转义。这发生在SQL之外,创建SQL,因此必须在LIKE转义步骤之后完成。对于MySQL,这是mysql_real_escape_string
和以前一样;对于其他数据库,将有一个不同的功能,你可以只使用参数化查询,以避免必须这样做。
导致混淆的问题是,在MySQL中,使用反斜杠作为两个嵌套转义步骤的转义字符!因此,如果您希望将字符串与文字百分号匹配,则必须使用双反斜杠转义并说LIKE 'something\\%'
。或者,如果它在PHP "
文字中,也使用反斜杠转义,"LIKE 'something\\\\%'"
。哎呀!
根据ANSI SQL,这是不正确的,它说:在字符串文字中,反斜杠意味着字面反斜杠,并且转义单引号的方式是''
;在LIKE表达式中,默认情况下根本没有转义字符。
因此,如果您希望以可移植的方式进行LIKE转义,则应使用LIKE ... ESCAPE ...
构造覆盖默认(错误)行为并指定自己的转义字符。为了理智,我们会选择除了该死的反斜杠之外的东西!
function like($s, $e) {
return str_replace(array($e, '_', '%'), array($e.$e, $e.'_', $e.'%'), $s);
}
$escapedname= mysql_real_escape_string(like($name, '='));
$query= "... WHERE name LIKE '%$escapedname%' ESCAPE '=' AND ...";
或带参数(例如PDO中):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
(如果你想要更多的可移植性派对时间,你也可以尝试考虑MS SQL Server和Sybase,其中[
字符在LIKE
语句中也是错误的,特殊的必须逃脱。唉。)
答案 1 :(得分:0)
没想到这么多年没人提,但如果你不需要做复杂的通配符匹配(例如foo%baz
),我认为INSTR
/LOCATE
/ POSITION
、LEFT
、RIGHT
等应该足够了。在我的所有案例中,我只使用 LIKE
来匹配字符串中的任何位置(即 %foobar%
),所以在所有关于转义 LIKE
模式的恐怖故事之后,我'我现在改用 INSTR
。
等价于 value LIKE '%foobar%'
(匹配任何地方):
INSTR(value, 'foobar') > 0
等价于 value LIKE 'foobar%'
(开始时匹配):
INSTR(value, 'foobar') = 1
等价于 value LIKE '%foobar'
(匹配结束):
RIGHT(value, 6) = 'foobar'
它可能不是那么直接和容易记住,最后匹配的解决方案也许可以以某种方式改进以更加通用。但是这些替代方案至少应该让您在安全方面放心,因为它绕过了任何自卷转义的需要,并且不需要您更改实际参数值(无论如何使用准备好的语句时)。< /p>