使用正则表达式验证电子邮件地址会造成伤害吗?

klu*_*utt 1 regex email validation

我听说使用正则表达式验证电子邮件地址是一件坏事,它实际上可能会造成伤害.这是为什么?我认为验证数据永远不会是件坏事.如果您正确执行验证,可能不必要,但绝不是坏事.你能解释一下为什么这是对还是错?如果它可能造成伤害,请举个例子.

her*_*tik 12

通常,是的 - 使用正则表达式来验证电子邮件地址是有害的.这是因为正则表达式的作者的错误(不正确)假设.

正如@Broman所说,电子邮件地址有两个部分,即local-partdomain.值得注意的是这些部分的一些事情并不是很明显:

  • local-part可以包含转义字符,甚至更多的@字符.
  • local-part可区分大小写的,但是它是由它想如何区分情况下特定域的邮件服务器.
  • domain部分可以包含由句点(.)分隔的零个或多个标签,但实际上没有与根(零标签)或gTLD(一个标签)本身对应的MX记录.

因此,您可以执行一些检查,而不会拒绝与上述内容相对应的有效电子邮件地址:

  • 地址至少包含一个 @
  • local-part(一切最右边的左边@)非空
  • domain部分(一切最右边的右边@)包含至少一个周期(同样,这并不完全正确,但务实)

而已.正如其他人所指出的那样,最好的做法是测试该地址的可传递性.这将确定两件重要的事情:

  1. 电子邮件当前是否存在; 和
  2. 用户可以访问电子邮件地址(是合法用户或所有者)

如果您在业务流程中构建电子邮件激活流程,则无需担心出现问题的复杂正则表达式.

进一步阅读以供参考:

RFC 5321:简单邮件传输协议

OWASP:输入验证备忘单

  • 至于可能造成的伤害 - 如果您有误报(拒绝有效的电子邮件地址),您就会拒绝合法用户,否则他们可能会为您的商品付费。 (2认同)
  • @MrMesees 从经济角度来看,阻止/拒绝潜在用户使用您的系统绝对是有害的,我不知道它怎么可能是这样。我在大多数网站上使用机密作为电子邮件字符串,例如“rogue+somesecretthing@abc.xyz”,并且我决定不在不允许“+”的网站上注册的次数不是个位数 (2认同)
  • @MrMeses 我同意。这是一个平衡问题。一方面,当然,用户可以拥有转义的双引号电子邮件地址,但这种情况非常罕见,您可能永远不会遇到它,而当您遇到时,说实话,该用户是故意深奥的,而您的网站不是他们第一次遇到问题。另一方面,诸如移动设备上的自动更正之类的打字错误经常发生,并且会在点后添加空格,并且也会给点击或转化带来障碍。不解决后者而支持前者似乎是不明智的。您可以允许 + 而不放弃正则表达式。 (2认同)

klu*_*utt 5

构建用于验证电子邮件的正则表达式可能是一个很好的有趣的练习,但一般来说,你应该在生产代码中真正避免使用它.

在大多数您想要使用它的情况下,只要知道电子邮件地址有效并不意味着什么.你真正想知道的是它是否是正确的电子邮件地址.验证这一点的正确方法是发送带有验证链接的邮件.

如果您使用验证链接验证了电子邮件地址,那么通常无需检查它是否是正确的电子邮件地址,因为您知道它有效.然而,它可以用于基本上检查用户是否在正确的字段中输入电子邮件地址.在这种情况下,我的建议是非常原谅.我会说只要检查它是否是现场的@就足够了.这是一个简单的检查,所有电子邮件地址都包含@.如果你想让它更复杂,我建议只是警告用户它可能是地址有问题,但不禁止它.

但更糟糕的是,准确验证电子邮件地址的正则表达式实际上是一个非常复杂的问题.如果你试图自己创建一个正则表达式,你几乎肯定会犯错误.值得一提的是,标准rfc5322允许在括号内进行注释.更糟糕的是,允许使用嵌套注释.标准正则表达式无法匹配嵌套模式.你需要扩展正则表达式.虽然扩展的正则表达并不罕见,但它确实说明了复杂性.即使你做对了,在新标准出现时你会更新正则表达式吗?

还有一件事,即使你100%正确,它仍然可能还不够.电子邮件地址的右侧是@和域部分左侧的本地部分.本地部分中的所有内容都应由服务器处理.当然,RFC 5322非常详细地说明了有效的本地部分是什么样的,但是如果某个特定的电子邮件服务器根据rfc5322接受无效的地址会怎么样?您是否确定不希望允许特定的电子邮件地址仅因为它不遵循标准而起作用?您是否因为选择了一个不起眼的电子邮件提供商而想要失去客户的商务?

如果您确实想检查生产代码中的地址是否正确,请使用MailAddress类或等效的东西.但是,如果这真的是你想要的话,首先花点时间思考一下.如果地址不正确,请问自己地址是否有任何价值.如果答案是否定的,则不然.请改用验证链接.

话虽这么说,验证输入可能是一件好事.重要的是要知道你为什么这样做.使用正则表达式或(最好)像Mailaddress类这样的东西验证电子邮件可以提供一些防止恶意输入的保护,例如SQL注入等.但如果这是你必须保护自己免受恶意输入的唯一方法,那么你正在做其他非常错误的事情.

  • 我同意需要验证链接,但这并不意味着验证毫无意义。 (3认同)
  • @klutt你通常试图为 luser(https://en.wikipedia.org/wiki/Luser) 设计你的软件,这可能最终会意外地输入错误的电子邮件地址。他将能够成功注册,但不会收到电子邮件,并且可能永远不会返回您的页面。当然,您无法捕捉到人们可能进入的所有形式的事物,但**尽可能地帮助他们**是有意义的。 (3认同)
  • @klutt 我不同意验证器可以捕获*某些*形式的用户输入错误(甚至是恶意输入,具体取决于如何定义)。这就是为什么物理地址经过充分验证的原因,尽管它们通常在发送/接受邮件之前无法“证明”。(物理地址比电子邮件地址更难验证,所以……再说一次,这就是外部*库和服务*的用途。) (2认同)

Min*_*ius 5

除了其他答案之外,我想指出我们的正则表达式引擎容易受到ReDOS - 正则表达式拒绝服务攻击。攻击基于这样一个事实,即许多非平凡的正则表达式的输入可能需要大量的 CPU 周期才能产生不匹配。

即使使用小型僵尸网络,制作此类输入也可能会给站点的可用性带来麻烦。

有关“正则表达式拒绝服务 (ReDOS) 攻击”的更多信息:https ://dzone.com/articles/regular-expressions-denial