转义字符,例如 $ 和 % | MySQL 和 PHP
Escaping Characters Such as $ and % | MySQL and PHP
所以基本上我一直在深入研究 MySQL 和 PHP 的领域......特别是在处理数据库和表单输入时我应该采取的安全措施。到目前为止,我发现强烈推荐以下内容:
- 准备好的语句
- 使用mysqli_real_escape_string()
- 不使用 Magic Quotes,因为它会混淆数据库并最终给你类似“你的名字不是……”的东西。
这一切都很棒,我一直在关注它。但是,我想知道是否还应该转义美元符号 [$]、百分号 [%] 以及可能的其他字符。查询不能将美元符号解释为 PHP 变量吗?我听说使用 % 符号甚至通配符的 LIKE 语法怎么样?准备好的语句在技术上应该处理所有这些,但我只是想安全并确保我正确地转义了所有内容。如果我忘记使用准备好的语句或者只是忽略了它们,我希望这个第二道防线可以让我不再头疼。
这是我目前用来转义的:
function escape($connection, $data){
$new_data = trim($data);
$new_data = mysqli_real_escape_string($connection, $new_data);
$new_data = addcslashes($new_data, '%_$');
$new_data = htmlspecialchars($new_data, ENT_NOQUOTES);
return $new_data;
}
这样合适吗?我做错了什么可怕的事吗?请注意,在检索数据库数据时,我必须删除 $、% 和 _ 字符前的反斜杠。
您不需要转义美元符号。 MySQL 不会特殊对待该字符,并且 PHP 只能在源代码中识别它,而不是在字符串值中识别它(除非您在字符串上调用 eval
,但这是另外一回事蠕虫)。
如果您使用用户输入作为 LIKE
的参数并且不希望用户能够使用通配符,则只需要转义 %
和 _
.如果您正在处理搜索表单,这可能会出现。存入数据库时不需要使用。
访问数据库时不需要使用htmlspecialchars
。仅当您在 HTML 页面中向用户显示数据时才应使用它,以防止 XSS 注入。
取决于数据的种类和用途。
如果您发现 PHP 默认准备好的语句太长太复杂而难以记住,我建议您查看 github 上可用的一些 classes 以让您了解简化查询。
一个很好的例子@
https://github.com/joshcam/PHP-MySQLi-Database-Class
使用此 class
插入查询的示例
$data = Array (
'login' => 'admin',
'active' => true,
'firstName' => 'John',
'lastName' => 'Doe',
'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")),
// password = SHA1('secretpassword+salt')
'createdAt' => $db->now(),
// createdAt = NOW()
'expires' => $db->now('+1Y')
// expires = NOW() + interval 1 year
// Supported intervals [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear
);
$id = $db->insert ('users', $data);
if ($id)
echo 'user was created. Id=' . $id;
else
echo 'insert failed: ' . $db->getLastError();
Am I doing something horrendously wrong?
是的。
首先是你的研究。
准备好的语句是您发现的唯一好东西。
虽然使用 mysqli_real_escape_string(假设您正在使用准备好的语句)将 无用且有害(产生您自己注意到的结果:“您名字不是……。”)。
魔术引号很久以前就已经从语言中删除了——因此,实际上没什么好担心的。
所以,即使你的大部分初始前提都是明显错误的。
现在回答你的问题。
Couldn’t the query interpret the dollar sign as a PHP variable perhaps?
没有
What about LIKE syntax I’ve heard that uses the % symbol or even the wildcard sign?
是的,你没有听错。这正是 LIKE 运算符的确切目的 - 执行通配符搜索。在 LIKE 中禁用这些符号毫无意义。
意味着每次您要使用 LIKE 运算符时,您都必须决定使用哪个特定符号以及禁止使用哪个符号。不能使用一劳永逸的解决方案。更不用说在所有其他 mysql 交互中 % 符号根本没有特殊意义。
Prepared statements should technically take care of all of this
预备语句与 $ 或 % 符号无关。准备好的语句处理 SQL 注入,但两个符号都不会导致它(你不会称 "injection" 为 LIKE 运算符的正确预期用途,对吗?)。
终于到了最恐怖的部分了。
如果您忘记使用准备好的语句或只是忽略使用它们,
没有什么可以拯救你。
您开发的功能对您的帮助最少。
总结一下。
- 摆脱这个功能。
- 使用占位符*来表示查询中的每个变量。
- 仅当输入数据中的
%
和 _
符号将在 LIKE 运算符中使用并且您不希望它们被解释时才转义。
- 使用 htmlspecialchars() 进行输出,而不是 mysql 输入。
*如果您不熟悉该术语,请阅读准备好的陈述。
所以基本上我一直在深入研究 MySQL 和 PHP 的领域......特别是在处理数据库和表单输入时我应该采取的安全措施。到目前为止,我发现强烈推荐以下内容:
- 准备好的语句
- 使用mysqli_real_escape_string()
- 不使用 Magic Quotes,因为它会混淆数据库并最终给你类似“你的名字不是……”的东西。
这一切都很棒,我一直在关注它。但是,我想知道是否还应该转义美元符号 [$]、百分号 [%] 以及可能的其他字符。查询不能将美元符号解释为 PHP 变量吗?我听说使用 % 符号甚至通配符的 LIKE 语法怎么样?准备好的语句在技术上应该处理所有这些,但我只是想安全并确保我正确地转义了所有内容。如果我忘记使用准备好的语句或者只是忽略了它们,我希望这个第二道防线可以让我不再头疼。
这是我目前用来转义的:
function escape($connection, $data){
$new_data = trim($data);
$new_data = mysqli_real_escape_string($connection, $new_data);
$new_data = addcslashes($new_data, '%_$');
$new_data = htmlspecialchars($new_data, ENT_NOQUOTES);
return $new_data;
}
这样合适吗?我做错了什么可怕的事吗?请注意,在检索数据库数据时,我必须删除 $、% 和 _ 字符前的反斜杠。
您不需要转义美元符号。 MySQL 不会特殊对待该字符,并且 PHP 只能在源代码中识别它,而不是在字符串值中识别它(除非您在字符串上调用 eval
,但这是另外一回事蠕虫)。
如果您使用用户输入作为 LIKE
的参数并且不希望用户能够使用通配符,则只需要转义 %
和 _
.如果您正在处理搜索表单,这可能会出现。存入数据库时不需要使用。
访问数据库时不需要使用htmlspecialchars
。仅当您在 HTML 页面中向用户显示数据时才应使用它,以防止 XSS 注入。
取决于数据的种类和用途。
如果您发现 PHP 默认准备好的语句太长太复杂而难以记住,我建议您查看 github 上可用的一些 classes 以让您了解简化查询。
一个很好的例子@ https://github.com/joshcam/PHP-MySQLi-Database-Class
使用此 class
插入查询的示例$data = Array (
'login' => 'admin',
'active' => true,
'firstName' => 'John',
'lastName' => 'Doe',
'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")),
// password = SHA1('secretpassword+salt')
'createdAt' => $db->now(),
// createdAt = NOW()
'expires' => $db->now('+1Y')
// expires = NOW() + interval 1 year
// Supported intervals [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear
);
$id = $db->insert ('users', $data);
if ($id)
echo 'user was created. Id=' . $id;
else
echo 'insert failed: ' . $db->getLastError();
Am I doing something horrendously wrong?
是的。
首先是你的研究。
准备好的语句是您发现的唯一好东西。
虽然使用 mysqli_real_escape_string(假设您正在使用准备好的语句)将 无用且有害(产生您自己注意到的结果:“您名字不是……。”)。
魔术引号很久以前就已经从语言中删除了——因此,实际上没什么好担心的。
所以,即使你的大部分初始前提都是明显错误的。
现在回答你的问题。
Couldn’t the query interpret the dollar sign as a PHP variable perhaps?
没有
What about LIKE syntax I’ve heard that uses the % symbol or even the wildcard sign?
是的,你没有听错。这正是 LIKE 运算符的确切目的 - 执行通配符搜索。在 LIKE 中禁用这些符号毫无意义。
意味着每次您要使用 LIKE 运算符时,您都必须决定使用哪个特定符号以及禁止使用哪个符号。不能使用一劳永逸的解决方案。更不用说在所有其他 mysql 交互中 % 符号根本没有特殊意义。
Prepared statements should technically take care of all of this
预备语句与 $ 或 % 符号无关。准备好的语句处理 SQL 注入,但两个符号都不会导致它(你不会称 "injection" 为 LIKE 运算符的正确预期用途,对吗?)。
终于到了最恐怖的部分了。
如果您忘记使用准备好的语句或只是忽略使用它们,
没有什么可以拯救你。
您开发的功能对您的帮助最少。
总结一下。
- 摆脱这个功能。
- 使用占位符*来表示查询中的每个变量。
- 仅当输入数据中的
%
和_
符号将在 LIKE 运算符中使用并且您不希望它们被解释时才转义。 - 使用 htmlspecialchars() 进行输出,而不是 mysql 输入。
*如果您不熟悉该术语,请阅读准备好的陈述。