Sql 带绑定参数的预处理语句优于带转义/引用参数的插值语句的原因
为了防止SQL注入,建议使用带有绑定值的预处理语句。这确保了数据库能够区分SQL中的实际逻辑(必须解析、解释和优化)和数据(不需要解释),因此不会解释和执行数据中的命令 实现某种保护的另一种方法是使用转义库,它解除数据中的重要字符,以便它们不会被解释 在我看来,一般来说,建议使用带有绑定参数的准备语句,而不是转义输入。例如,带有绑定值的准备语句在循环中确实有一些性能优势 我的问题:是否有任何安全原因让我们更喜欢带有绑定值的语句而不是转义语句?如果是,具体原因是什么Sql 带绑定参数的预处理语句优于带转义/引用参数的插值语句的原因,sql,sql-injection,Sql,Sql Injection,为了防止SQL注入,建议使用带有绑定值的预处理语句。这确保了数据库能够区分SQL中的实际逻辑(必须解析、解释和优化)和数据(不需要解释),因此不会解释和执行数据中的命令 实现某种保护的另一种方法是使用转义库,它解除数据中的重要字符,以便它们不会被解释 在我看来,一般来说,建议使用带有绑定参数的准备语句,而不是转义输入。例如,带有绑定值的准备语句在循环中确实有一些性能优势 我的问题:是否有任何安全原因让我们更喜欢带有绑定值的语句而不是转义语句?如果是,具体原因是什么 我可能想到的一个原因是“转义很
我可能想到的一个原因是“转义很棘手”,转义库需要与数据库功能完全匹配。。。还有什么吗?一个原因是转义仅用于保护带引号的字符串文本。例如(我将使用伪代码,因为您没有引用任何特定的编程语言): 在上面的示例中,撇号应该转义,因此它将成为
WHERE name='O'Reilly'
,因此可以安全地插入SQL查询,而不会导致任何错误
但是,数字不需要在SQL中引用,对包含撇号的字符串进行转义将不会起到正确的作用:
$escapedId = EscapeString("123'456")
$sql = "SELECT * FROM MyTable WHERE id = $escapedId"
这将导致其中id=123\456
,这仍然是一个错误
您可能会说,“我们将数字放在单引号中”,但这并不总是可能的,例如MySQL中的LIMIT
子句需要实整数,而不是包含数字的带引号的字符串
除了上述问题,使用参数编写代码比使用转义更容易
例如,您可以编写如下代码:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES ('" . mysqli_real_escape_string($_POST['col1']) . "', "
. $mysqli->real_escape_string($_POST['col2']) . "', '"
. $mysqli->real_escape_string($_POST['col3']) . "', '"
. $mysqli->real_escape_string($_POST['col4']) . ", '"
. $mysqli->real_escape_string($_POST['col5']) . "', '"
. $mysqli->real_escape_string($_POST['col6']) . "')";
你能找出错误吗?有足够的时间,我相信你能做到。但是它会减慢你的编码速度,并且在你寻找缺少的引号字符和其他错误时会让你眼睛疲劳
但写这篇文章要容易得多,之后也更容易阅读:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES (?, ?, ?, ?, ?, ?)";
查询参数对于更多的数据类型是安全的,它们可以帮助您更快地编写代码,并且错误更少。这是一个巨大的胜利。整个问题的陈述都来自一个古老的严重错觉 解除数据中重要字符的转义 坦白说,这是胡说八道
- 没有包罗万象的“重要人物”。如果一个字符被切断,可能会对一个查询部分产生毁灭性的影响,那么它可能像另一个查询部分中的羔羊一样无害。反之亦然
- 没有抽象的包罗万象的“数据”。所有查询部分都是不同的,但转义只适用于一个部分
- 而且根本没有“用逃跑来保护”这样的做法
与转义不同,准备好的语句总是确保正确处理查询部分。虽然我没有经验证据证明使用了它,但也许值得指出的是,使用混合使用参数变量和常量值的准备语句
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES (?, ?, ?, ?, ?, ?)";
--we could infer that name will vary and type will not
--but we'd have to analyze all queries sent to work this out
SELECT * FROM person WHERE type = 1 AND name = 'john'
SELECT * FROM person WHERE type = 1 AND name = 'mark'
SELECT * FROM person WHERE type = 1 AND name = 'luke'
--we can easily say that type will vary and name will too
--the previously seen queries would infer differently
SELECT * FROM person WHERE type = @t AND name = @n
sayHello(string name){
console.print("hello " + name);
}
var name = console.readString(),
sayHello(name);
main(){
disk.write("sayHello(string name){console.print(\"hello \"" + name +");}", "c:\\temp\\new.lang");
launchExe("langcompiler.exe", "c:\\temp\\new.lang");
launchExe("c:\\temp\\new.exe");
}