我正在检查对这样的数据库的输入:
myForm1.Refresh();
然后:
$email = $_POST['newsletter_email'];
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
问题是,它足够好吗?或者我也应该使用$is_user = $db->count_rows('users', "WHERE email='" . $email . "'");
?
答案 0 :(得分:3)
这个问题分为两部分。
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if ($email !== false) {
// Well, you've got yourself a valid email address!
}
请勿使用mysql_real_escape_string()
。 prevent SQL Injection的正确方法是使用参数化查询。也称为准备陈述。
推荐阅读:
您的代码应如下所示:
$stmt = $db->prepare('SELECT count(userid) FROM users WHERE email = ?');
if ($stmt->exec([ $email ])) {
$is_user = $stmt->fetchColumn(0);
}
如果这对您来说太麻烦,您可以加载EasyDB库并使查询看起来像这样:
$is_user = $db->cell('SELECT count(userid) FROM users WHERE email = ?', $email);
请停止使用输入转义并采用预备语句。他们将查询和参数发送到不同的数据包中,这意味着即使使用Unicode黑客攻击也无法改变查询结构。
您必须正确使用预准备语句(即永远不要将用户输入与传递给prepare()
的查询字符串连接起来)以实现这种保证的安全级别。
此外,在PHP中,某些驱动程序默认模拟准备好的语句。来自PHP manual:
PDO :: ATTR_EMULATE_PREPARES启用或禁用预准备语句的模拟。某些驱动程序不支持本机预处理语句或对它们的支持有限。使用此设置可强制PDO始终模拟预准备语句(如果
TRUE
),或尝试使用本机预准备语句(如果FALSE
)。如果驱动程序无法成功准备当前查询,它将始终回退到模拟预准备语句。需要布尔。
模拟预处理语句不提供与真实预处理语句相同的安全保证(即data/instruction separation)。为安全起见,请禁用模拟准备。
$db = new PDO(/* etc */);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
答案 1 :(得分:0)
你正在"消毒"而不是"验证"输入。仅仅因为您使用FILTER_SANITIZE_EMAIL
,并不意味着输入是电子邮件地址。所以是的,在你的例子中mysql_real_escape_string()
将是一个明智的选择。
<?php
$email = filter_var($_POST['newsletter_email'], FILTER_SANITIZE_EMAIL);
// Validate the post data as an email address.
IF (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$cln_email = mysql_real_escape_string($email);
$is_user = $db->count_rows('users', "WHERE email='" . $cln_email. "'");
}
?>