我正在阅读Does $_SESSION['username'] need to be escaped before getting into an SQL query?并且它说“你需要转义你传递给sql查询的每个字符串,无论其来源如何”。现在我知道这样的事情是非常基本的。谷歌搜索结果超过20,000。 Stackoverflow本身只有20页的结果,但没有人真正解释什么是字符串转义或如何做。这只是假设。你能帮助我吗?我想学习,因为我一直在用PHP制作一个Web应用程序。
我看过: Inserting Escape Characters,What are all the escape characters in Java?, Cant escape a string with addcslashes(), Escape character, what does mysql_real_escape_string() really do?, How can i escape double quotes from a string in php?, MySQL_real_escape_string not adding slashes?, remove escape sequences from string in php我可以继续,但我相信你明白了。这不是懒惰。
答案 0 :(得分:117)
转义字符串意味着减少该字符串中使用的引号(和其他字符)的歧义。例如,当您定义字符串时,通常用双引号或单引号括起来:
"Hello World."
但是如果我的字符串中有双引号怎么办?
"Hello "World.""
现在我有歧义 - 翻译不知道我的字符串在哪里结束。如果我想保留双引号,我有几个选择。我可以在我的字符串周围使用单引号:
'Hello "World."'
或者我可以逃避我的报价:
"Hello \"World.\""
以斜杠开头的任何引号都是转义,并且被理解为字符串值的一部分。
在查询方面,MySQL有一些它所关注的关键字,我们不能在查询中使用这些关键字而不会造成一些混淆。假设我们有一个值表,其中一列被命名为“Select”,我们想要选择:
SELECT select FROM myTable
我们现在在查询中引入了一些含糊之处。在我们的查询中,我们可以通过使用反向标记来减少这种模糊性:
SELECT `select` FROM myTable
这消除了我们在选择字段名称时使用不良判断所引入的混淆。
只需将您的值传递给mysql_real_escape_string()
,即可为您处理很多问题。在下面的示例中,您可以看到我们通过此函数传递用户提交的数据,以确保它不会对我们的查询造成任何问题:
// Query
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
存在用于转义字符串的其他方法,例如add_slashes
,addcslashes
,quotemeta
等,但您会发现当目标是运行安全查询时,大型开发人员更喜欢mysql_real_escape_string
或pg_escape_string
(在PostgreSQL的上下文中。
答案 1 :(得分:19)
某些字符对您正在使用的SQL数据库有特殊意义。在查询中使用这些字符时,它们可能会导致意外和/或意外行为,包括允许攻击者危害您的数据库。为了防止这些字符以这种方式影响查询,需要对其进行转义,或者以不同的方式说明,需要告知数据库不要将它们视为此查询中的特殊字符。
如果是mysql_real_escape_string()
,它会逃脱\x00
,\n
,\r
,\
,'
,"
和\x1a
因为这些,如果没有转义,可能会导致前面提到的问题,其中包括使用MySQL数据库进行SQL注入。
答案 2 :(得分:1)
为简单起见,您基本上可以想象反斜杠“ \”是运行时传递给解释器的命令。
例如在解释此语句时:
$txt = "Hello world!";
在词法分析阶段(或将语句拆分为单独的标记时),这些将是已识别的标记
$
,txt
,=
,"
,Hello world!
,"
和;
但是,字符串中的反斜杠将导致额外的标记集,并被解释为使用紧随其后的字符进行操作的命令: 例如
$txt = "this \" is escaped";
产生以下令牌:
$
,txt
,=
,"
,this
,\
,"
,is escaped
,{{ 1}}和"
解释器已经基于;
令牌后的字符知道(或具有它可以采用的预设路线)该做什么。因此,对于\
,它将继续将其视为字符而不是字符串结尾命令。