关于PHP准备语句转义的清晰度

时间:2016-01-09 10:14:25

标签: php mysqli pdo

我知道这是一个非常受欢迎的问题,而且经过多个小时的研究,我仍然对确定的答案有点不确定。我不是PHP的专家,现在已经自学了一段时间了。我最近刚刚掌握了MYSQLi准备好的陈述(已经习惯了以前的做法)。

我的主要问题是在使用预准备语句时,试图找到关于使用真实转义字符串(或任何其他安全性)的要求的确定答案。

我已准备好通过以下问题:

Prepared Statements, escape variables

IF I use mysqli prepared statements do i need to escape

Do PHP PDO prepared statments need to be escaped?

但是在使用预准备语句时似乎存在支持和反对转义数据的论据。还有很多关于PDO的提及对我来说非常混乱,因为我不是PHP的天才。

我期待这个伟大的社区帮助我完全理解并给我一个答案(以某种方式,我希望能理解),以便我进步。

为此,我有以下例子,并询问是否有人可以用非专业术语解释哪些不使用,哪些不使用,更重要的是,为什么?

我目前正在整个代码中使用它:

$qry = $conn->prepare('INSERT INTO status (id, name, message, date) VALUES (?, ?, ?, NOW())');
$qry->bind_param('iss', $_POST['id'], $_POST['name'], $_POST['message']);
$qry->execute();
$qry->close();

但是,我对上述示例问题的理解有限,告诉我使用以下代码是安全/可行的:

vector<Parent>

那么,哪种方法最好?抱歉这个冗长的问题。研究过它并试图理解它我只想确定原因。

感谢大家的时间和支持,我非常感谢您提供的任何帮助。

3 个答案:

答案 0 :(得分:3)

注意:这个答案使用了一个过于简单化的模型,说明了逃避和准备语句实际上做了什么。

SQL是一种语言。其中的一些字符具有特殊含义。例如,'分隔字符串的开头和结尾。

当您转义数据时,您将\放在具有特殊含义的字符前面。这导致它们意味着(例如)“撇号”而不是“字符串的结尾”。

所以:

$id = $conn->real_escape_string($_POST['id']);

现在,如果ID中有',则不会破坏SQL。

当您使用绑定变量时,它将自动为您转义。

$qry->bind_param('iss', $id, $name, $message);

现在,如果ID中有',则不会破坏SQL。

......除了你已经这样做了。

现在,您已将'变为\',然后转入\\\',因为'已转义,然后再次与{{1}一起转义从第一次逃跑开始。

所以现在第一个\被视为数据(而不是特殊的SQL字符)并被插入到数据库中。

使用准备好的陈述。使用预备语句。

(例外情况是当您使用变量而不能执行准备好的语句时,例如动态表名称,这应该不常见)。

答案 1 :(得分:1)

如果您使用预准备语句,则绝对不需要使用real_escape_string()或任何其他类似函数来转义参数。事实上,如果你逃避它,你最终可能会获得双重转义值。

你的第二个例子完全有效。

答案 2 :(得分:1)

答案在PHP docs

中关于准备陈述的文章中说明
  

转义和SQL注入

     

绑定变量与查询分开发送到服务器,因此不会干扰它。在解析语句模板之后,服务器直接在执行点使用这些值。绑定参数不需要转义,因为它们永远不会直接替换为查询字符串。 [...]

     

这种分离有时被认为是防止SQL注入的唯一安全功能,但如果所有值都正确格式化,则可以使用非预处理语句实现相同程度的安全性。应该注意的是,正确的格式与转义不同,涉及的逻辑比简单的转义更多。因此,准备好的语句对于这个数据库安全元素来说只是一种更方便,更不容易出错的方法。

(强调我的)

请注意,在绑定参数之前,数据库引擎会编译预准备语句。它确实是能够使用参数执行此查询的数据库引擎。在任何时候都没有创建一个SQL字符串,它将准备好的SQL语句的字符串与参数的字符串版本连接起来。

将SQL视为我们人类的语言。另一方面,数据库引擎在它可以执行任何操作之前不需要在纯SQL字符串中包含所有内容。相反,它需要先解析SQL才能执行任何操作。所以它可以处理两条信息(准备好的声明,参数) 无需先构建完整的SQL字符串即可生成所需的输出。并且因为它不构建该字符串,所以它也不需要转义任何东西。不会为SQL构造解析参数(这将是SQL注入风险)。它们被用作值,仅此而已。