关于PHP语句转义的澄清

关于PHP语句转义的澄清,php,mysqli,pdo,Php,Mysqli,Pdo,我知道这是一个很受欢迎的问题,经过数小时的研究,我仍然有点不确定最终的答案。我不擅长PHP,并且已经自学了一段时间了。我最近才开始考虑MYSQLi准备的语句(已经习惯了旧的做法) 我的主要问题是试图找到一个明确的答案,当使用准备好的语句时,需要使用真正的转义字符串(或任何其他安全性) 我已准备好回答以下问题: 但是,在使用准备好的语句时,似乎有理由和反对转义数据。还有很多人提到PDO,对我来说,PDO非常令人困惑,因为我不是PHP的天才 我期待着这个伟大的社区帮助我完全理解,并给我一个答案

我知道这是一个很受欢迎的问题,经过数小时的研究,我仍然有点不确定最终的答案。我不擅长PHP,并且已经自学了一段时间了。我最近才开始考虑MYSQLi准备的语句(已经习惯了旧的做法)

我的主要问题是试图找到一个明确的答案,当使用准备好的语句时,需要使用真正的转义字符串(或任何其他安全性)

我已准备好回答以下问题:

但是,在使用准备好的语句时,似乎有理由和反对转义数据。还有很多人提到PDO,对我来说,PDO非常令人困惑,因为我不是PHP的天才

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

为此,我举了以下几个例子,问是否有人可以用外行的术语解释使用哪个,不使用哪个,更重要的是,为什么

我目前在我的整个代码中都在使用:

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

$qry = $conn->prepare('INSERT INTO status (id, name, message, date) VALUES (?, ?, ?, NOW())');
$qry->bind_param('iss', $id, $name, $message);
$qry->execute();
$qry->close();
但是,我对上述示例问题的有限理解告诉我,使用以下代码是安全的/可以的:

$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();
那么,哪种方法最好?对不起,这个冗长的问题。经过研究并试图理解它,我只想确定并理解其中的原因


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

如果您使用准备好的语句,您肯定不需要使用
real\u escape\u string()
或任何其他类似函数来转义参数。事实上,如果对其进行转义,最终可能会得到两个转义值


您的第二个示例是完全有效的。

如果您使用准备好的语句,您肯定不需要使用
real\u escape\u string()
或任何其他类似函数来转义参数。事实上,如果对其进行转义,最终可能会得到两个转义值


你的第二个例子是完全正确的。

答案在以下关于准备好的陈述的文章中陈述:

转义和SQL注入

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

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

(我的重点)

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

把SQL看作是我们人类的一种语言。另一方面,DB引擎在执行任何操作之前,不需要将所有内容都用简单的SQL字符串表示。相反,它需要先解析SQL,然后才能执行任何操作。因此,它可以使用两条信息(准备好的语句、参数)来
无需首先构建完整的SQL字符串即可生成所需的输出。因为它不构建字符串,所以也不需要转义任何内容。对于SQL构造,不会再次解析参数(这将是SQL注入风险)。它们被用作值,仅此而已。

答案在以下关于准备语句的文章中说明:

转义和SQL注入

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

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

(我的重点)

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

把SQL看作是我们人类的一种语言。另一方面,DB引擎在执行任何操作之前,不需要将所有内容都用简单的SQL字符串表示。相反,它需要先解析SQL,然后才能执行任何操作。因此,它可以使用两条信息(准备好的语句、参数)来
无需首先构建完整的SQL字符串即可生成所需的输出。因为它不构建字符串,所以也不需要转义任何内容。对于SQL构造,不会再次解析参数(这将是SQL注入风险)。它们被用作值,仅此而已。

NB:这个答案使用了一个-s
$id = $conn->real_escape_string($_POST['id']);
$qry->bind_param('iss', $id, $name, $message);