为了防止 SQL 注入,建议使用带有绑定值的准备好的语句。这确保了数据库可以区分 SQL 中的实际逻辑(必须被解析、解释和优化)和数据(不需要解释),因此不会解释和执行在数据中找到的命令.
另一种实现某种保护的方法是使用转义库,它可以解除数据中的重要字符,这样它们就不会被解释。
在我看来,通常建议使用带有绑定参数的准备好的语句而不是转义输入。例如,带有绑定值的准备好的语句确实在循环中具有一些性能优势。
我的问题:是否有任何安全原因更喜欢带有绑定值的准备语句而不是转义?如果是,确切原因是什么?
我可能会想到的一个原因是“转义很棘手”并且转义库需要与数据库功能完全匹配……还有什么?
原因之一是转义仅适用于保护带引号的字符串文字。例如(我将使用伪代码,因为您没有引用任何特定的编程语言):
$escapedName = EscapeString("O'Reilly")
$sql = "SELECT * FROM MyTable WHERE name = '$escapedName'"
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,撇号应该被转义,所以它会变得WHERE name = 'O\'Reilly'安全,因此可以安全地插入到 SQL 查询中而不会导致任何错误。
但是,在 SQL 中不需要引用数字,并且转义包含撇号的字符串不会做正确的事情:
$escapedId = EscapeString("123'456")
$sql = "SELECT * FROM MyTable WHERE id = $escapedId"
Run Code Online (Sandbox Code Playgroud)
这将导致WHERE id = 123\'456which 仍然是一个错误。
您可能会说,“把数字放在单引号中”,但这并不总是可行的,例如LIMITMySQL 中的子句需要实整数,而不是包含数字的带引号的字符串。
除了上述问题之外,使用参数而不是使用转义来编写代码更容易!
例如,您可以编写如下代码:
$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']) . "')";
Run Code Online (Sandbox Code Playgroud)
你能发现错误吗?有足够的时间,我相信你可以。但它会减慢您的编码速度,并可能让您在寻找丢失的引号字符和其他错误时眼睛疲劳。
但是写这个要容易得多,之后也更容易阅读:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES (?, ?, ?, ?, ?, ?)";
Run Code Online (Sandbox Code Playgroud)
查询参数对于更多数据类型是安全的,它们可以帮助您更快地编写代码,减少错误。这是一个很大的胜利。
| 归档时间: |
|
| 查看次数: |
163 次 |
| 最近记录: |