PHP的内置filter_input是否正常工作?

时间:2011-02-23 15:56:38

标签: php zend-framework filtering

我尝试了PHP的内置函数: filter_input()

var_dump(filter_var('john.doe.@gmail.com', FILTER_VALIDATE_EMAIL));

输出:

  

string(19)“john.doe。@ gmail.com”

然后我尝试了最新版本的Zend Framework(1.11.3):

$validator = new Zend_Validate_EmailAddress();  
if ($validator->isValid('john.doe.@gmail.com')) {
    echo 'OK';
} else {
    foreach ($validator->getMessages() as $message) {
            echo "$message\n";
    }
}

输出:

  

'john.doe'。不能与点原子格式匹配
  'john.doe。'不能与引号字符串格式匹配
  'john.doe。'在电子邮件地址'john.doe。@ gmail.com'

中没有有效的本地部分

内置函数应返回FALSE或Zend方法返回'OK'。

我的中心问题是:
哪一个是对的?

3 个答案:

答案 0 :(得分:2)

http://framework.zend.com/manual/en/zend.validate.set.html并没有真正表明他们是否严格遵守RFC,所以让我们来看看源代码。

在源代码中,_validateLocalPart()定义了它们匹配的EBNF:

    // Dot-atom characters are: 1*atext *("." 1*atext)
    // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
    //        "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
    if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) {

看起来他们肯定会严格遵守 - 因此本地部分不能以点开头或结尾。

上面的模式与rfc2822规范中的完全相同:http://www.ietf.org/rfc/rfc2822.txt - Zend / Validate / EmailAddress.php中的isValid docblock将其引用为2822。

所以,如果你想要符合rfc2822,那么Zend_Validate_EmailAddress就是正确的,而且filter_input很可能是不符合规范的。

答案 1 :(得分:1)

可能只是Zend_Engine严格匹配RFC(对于电子邮件而言是3英里长)。我怀疑,严格来说,句号是允许的字符,但是不允许在@位置之前的句号,所以这可能是问题所在。

我将假设gmail仍然允许发送john.doe。@ gmail.com。如果是这种情况,问题就变得更多的是你是否真的想要严格匹配RFC,或者只是在允许的电子邮件地址中允许它不会伤害你的系统。

如果你担心sql注入,请在sql&中绑定你的变量。逃避你的HTML,因为不能保证rfc的严格匹配实际上可以防止这样的问题。

如果您担心电子邮件是可发送/可接收的,我建议只是发送预期收据,或使用确认链接设置可选的电子邮件确认系统。

如果您担心电子邮件标题注入,这是在发送邮件时使用电子邮件库的一个很好的理由,我希望zend有一个强大的邮件库。

TooLongDidn'tRead; 我的建议是:

  • 宽容。 (所以使用哪个选项更宽松,在本例中为filter_input)
  • 通过发送电子邮件来测试电子邮件是否有效,这几乎是唯一真正的测试。
  • html-escape& sql-bind什么时候在html或sql中使用它,并且不相信任何来自危险世界的东西,无论何时你使用它。
  • 请勿使用可利用的php邮件(),使用可防止邮件头注入的库。

答案 2 :(得分:1)

它还取决于您拥有的PHP版本。 PHP 5.2.14及更高版本(以及5.3)具有更新的正则表达式(请参阅the commit to the PHP source code)。 PHP 5.2.13RC2及更低版本具有旧的正则表达式。另请参阅Bug #49576