我环顾四周,找不到我的问题的答案。
我将最新的 PHP 用于服务器端脚本,将 MySQL 用于我的数据库。字符集utf8mb4
是否有所作为。
到目前为止,我一直使用准备好的语句来保护自己免受 SQL 注入。但是,由于我的大多数查询只执行一次,所以代码真的很慢。当我$conn->query()
改为使用$conn->real_escape_string()
所有变量时,它会更快。
但是,$conn->real_escape_string()
也很慢,因为每次通话都有一个往返。但我不明白为什么需要往返,因为我觉得转义函数可以用 PHP 编程。
从文档中,函数看起来像这样:
编码的字符为 NUL (ASCII 0)、\n、\r、\、'、" 和 Control-Z。
function sanitize($str)
{
str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
}
假设我确保它采用正确的编码并且它不是空的。
这在其中一个文档中作为评论发布。顺便说一句,str_replace
适用于 Unicode。
但是,我想到了一些更有意义的东西。看看这个页面,我可以进一步扩展。对于这样的声明:
$sql = "UPDATE ipsum SET lorem=$str WHERE id=1337";
我不能这样做(我正在事先检查以确保它是 UTF-8):
function sanitize($str)
{
return "'" .str_replace(array("\\", "'"), array("\\\\", "\\'"), $str) . "'";
}
这将防止 SQL 注入?为什么不?我想不出它会失败的输入。
如果没有,是否有更好的 PHP 函数可以更好地防止 SQL 注入?
提前致谢!您可以在此处测试 SQL 。
更新:收到了我预期的回复。澄清一下,我并不是要你发表你的经典讲道“准备好的陈述是最好的事情,否则就死了”。如果我想要,我会在 Yahoo! 上询问。答案不在这里。
我想知道为什么我的方法(第二种)不安全(或者如果是)。最好包括讨论什么real_escape_string
或准备好的语句实际上对数据进行了清理。MySQL 和 PHP 都是开源的,我相信有人知道调用这些函数时会发生什么。
我根本不明白为什么需要往返来清理字符串。像这样的方法怎么不能在 PHP 中实现?
更新 2:我已经遍历了所有的 unicode 字符(0x0000 到 0x1F77F,在 Wikipedia 上找到了这个)并注意到,如果real_escape_string()
只转义单个字符而不是短语(根据文档它确实如此),在utf8mb4
字符集下,改变的字符是:
Unicode 0 => \0
unicode 10 =>\n
unicode 13 =>\r
unicode 26 =>\Z
Unicode 34 =>\"
unicode 39 =>\'
unicode 92 =>\\
因此,即使它是utf8mb4
,它也与文档所说的没有什么不同(猜测是因为 UTF-8 是标准的)。那么为什么这不能在 PHP 中实现呢?
这是一个PHP 脚本,它结合了所有这些 unicode 并对其进行清理。这是一个SQL fiddle。