Col*_*mbo 38 php mysql escaping
在我使用的旧服务器上,我无法使用预准备语句,我目前正在尝试完全转义用户输入,然后再将其发送到MySQL.为此我使用PHP函数mysql_real_escape_string
.
由于这个函数没有逃脱MySQL通配符%和_我也用它addcslashes
来逃避这些.
当我发送类似的东西:
test_test " '
Run Code Online (Sandbox Code Playgroud)
到数据库然后读回数据库显示:
test\_test " '
Run Code Online (Sandbox Code Playgroud)
看着这个我无法理解为什么_有一个前面的反斜杠但是'和'没有.因为它们全部用\ _确定_'并且"应该都显示相同,即所有都具有转义字符可见或一切都没有可见.
是否会自动筛选转义
有谁能解释一下?
bob*_*nce 89
_
并且%
通常不是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-escape,则应使用该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 ...";
Run Code Online (Sandbox Code Playgroud)
或带参数(例如在PDO中):
$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ...");
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR);
Run Code Online (Sandbox Code Playgroud)
(如果你想要更多的可移植性派对时间,你也可以尝试考虑MS SQL Server和Sybase,其中[
角色在一个LIKE
语句中也是错误的,特殊的,并且必须被转义.agh.)
令人惊讶的是这么多年之后没有人愿意提及它,但如果您不需要进行复杂的通配符匹配(例如foo%baz
),我认为INSTR
/ LOCATE
/ POSITION
、LEFT
、RIGHT
等应该足够了。在我的所有情况下,我只用来LIKE
匹配字符串中的任何位置(即,例如%foobar%
),因此在经历了所有关于转义模式的恐怖故事之后LIKE
,我现在正在使用INSTR
。
等价于value LIKE '%foobar%'
(任何地方匹配):
INSTR(value, 'foobar') > 0
Run Code Online (Sandbox Code Playgroud)
相当于value LIKE 'foobar%'
(开始时的匹配):
INSTR(value, 'foobar') = 1
Run Code Online (Sandbox Code Playgroud)
等价于value LIKE '%foobar'
(结束时匹配):
RIGHT(value, 6) = 'foobar'
Run Code Online (Sandbox Code Playgroud)
它可能不那么直接和容易记住,最后的匹配解决方案也许可以以某种方式改进以更加通用。但这些替代方案至少应该让您在安全性方面感到安心,因为它绕过了任何自滚动转义的需要,并且不需要您更改实际的参数值(无论如何使用准备好的语句时)。
归档时间: |
|
查看次数: |
27005 次 |
最近记录: |