我正在is_email()
检查用户提供的电子邮件地址是否有效。例如:
$email = $_POST['email'];
if ( is_email( $email ) )
// Do something.
据我所知,此函数中没有任何内容可将信息写入数据库。$email
在将其传递给功能之前是否应该进行消毒?
我正在is_email()
检查用户提供的电子邮件地址是否有效。例如:
$email = $_POST['email'];
if ( is_email( $email ) )
// Do something.
据我所知,此函数中没有任何内容可将信息写入数据库。$email
在将其传递给功能之前是否应该进行消毒?
Answers:
看一下is_email()
trac 上的功能,您似乎不需要进行简单的测试,因为它只是字符串测试。我什至可以说,如果该函数返回true,则无需在将其发送到数据库之前对其进行清理。
该is_email()
函数源是一个典型的WordPress的实现,不具有什么样的工作完全RFC 6531允许。原因之一可能是,根据Internet工程任务组(IETF®)指南,默认的PHP FILTER_VALIDATE_EMAIL
常量filter_var()
在验证某些内容方面并不好得多。
关键是RFC 6531允许“超出ASCII范围的Unicode字符”。即是(对于本地部分-之前的@
):
- 大写和小写英文字母(az,AZ)(ASCII:65–90、97–122)
- 转换
0
为9
(ASCII:48–57)- 这些特殊字符:
! # $ % & ' * + - / = ? ^ _ ` { | } ~
- 字符
.
(点,句点,句号)(ASCII:46),前提是它不是第一个或最后一个字符,并且还不能连续出现(例如John..Doe@example.com
,不允许)。- 特殊字符是有限制的。他们是:
- 空格和
"(),:;<>@[\]
(ASCII:32、34、40、41、44、58、59、60、62、64、91–93)- 特殊字符的限制是必须仅在引号之间使用特殊字符,并且其中两个字符(反斜杠\和引号“(ASCII:92,34))也必须带有反斜杠
\
(例如"\\"
和"\""
) 。- 注释可以在局部的任何一端加上括号。例如
john.smith(comment)@example.com
和(comment)john.smith@example.com
都等同于"john.smith@example.com"
,但john.(comment)smith@example.com
将无效。U+007F
RFC 6531允许使用编码为UTF-8的上述国际字符,尽管邮件系统可能会在分配本地部分时限制使用哪些字符。
对于全局/域部分:
电子邮件地址的域名部分必须符合严格的准则:它必须符合主机名的要求,该主机名由字母,数字,连字符和点组成。另外,域部分可以是IP地址文字,并用方括号括起来,例如
jsmith@[192.168.2.1]
或jsmith@[IPv6:2001:db8::1]
[…]
这可能会导致奇怪但有效的电子邮件地址,如下所示:
localpart.ending.with.dot.@example.com
(comment)localpart@example.com
"this is v@lid!"@example.com
"much.more unusual"@example.com
postbox@com
admin@mailserver1
"()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
" "@example.org
资料来源: php.net/作者gt@kani.hu –本文作者固定的示例
还有本地和域长度限制:
电子邮件地址的格式是
local-part@domain
在本地部分可以是最多64个字符长和域名可以具有最大的253个字符 -但最大256个字符长度的正向或反向路径的限制整个电子邮件地址是没有长度超过254个字符。[2]的正式定义在RFC 5322(第3.2.3和3.4.1)和RFC 5321 -与在信息RFC 3696 [3]和相关联的勘误表给出一个更可读的形式。
资料来源:维基百科
这就是WordPress检查的内容:
strlen( $email ) < 3
strpos( $email, '@', 1 ) === false
!preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
preg_match( '/\.{2,}/', $domain )
trim( $domain, " \t\n\r\0\x0B." ) !== $domain
$subs = explode( '.', $domain );
然后
2 > count( $subs )
trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
!preg_match('/^[a-z0-9-]+$/i', $sub )
资料来源:WP Core v4.0
上述所有情况将触发is_email()
返回false。结果是可过滤的(可以附加回调),过滤器将具有三个参数,最后一个参数是原因。例:
return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );
这意味着您可以覆盖特定检查返回的结果。
这允许您添加特殊检查,例如允许Umlaut域,仅TLD的域部分等。
WordPress在大多数情况下都是安全的,但由于邮件服务器实际上必须符合RFC的要求,因此更具限制性。请记住,并非每个邮件服务器都符合RF 6531准则。
有趣的副作用:内部有两个相关功能~/wp-includes/formatting
:is_email()
和sanitize_email()
。它们实际上是相同的功能。我不知道为什么有人认为将函数内容从一个复制到另一个是一个好主意,而不仅仅是将一个作为回调添加到另一个提供的过滤器中。由于v0.71和v1.5相同,因此我个人会在以后使用清理后的字符串时使用后者。请注意,甚至声明它不符合RFC。is_email()
sanitize_email()
is_email()
消毒所有东西!
安全的基本规则之一是永远不要信任用户的输入。通常,我不在乎is_email()或任何其他特定函数的实现,或者该函数是否会对我提供的内容造成任何危险。也许实施会有一天会改变。谁知道。我必须假设它可以被破坏。始终应该假设用户输入是积极的敌意,对于最终发往数据库的任何东西都是双重的,并且在将用户输入移交给某些功能之前先对其进行净化。这只是良好的常规安全卫生措施。