PHP Regex用于人名

时间:2009-08-11 16:01:21

标签: php regex names

我遇到了一个用于人类名字的正则表达式的问题。

$rexName = '/^[a-z' -]$/i';

假设名为Jürgen的用户希望注册?还是Böb?这在欧洲非常普遍。有没有特别的符号呢?

编辑:,只是把Jürgen的名字扔给了一个正则表达式的创造者,它把这个词分成了字母......

http://www.txt2re.com/index.php3?s=J%FCrgen+Blalock&submit=Show+Matches

EDIT2:好的,因为检查这些特定的东西很难,为什么不使用只检查非法字符的正则表达式呢?

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";

(现在哪些实际上可以用于任何黑客攻击?)

例如。这允许'和 - 标志,但你需要一个;使它在SQL中工作,那些将被停止。任何其他常用于HTML注入SQL攻击的字符,我都缺少?

4 个答案:

答案 0 :(得分:21)

我真的会说:不要试图验证名称:有一天,你的代码会遇到一个它认为“错误”的名字......你觉得当应用程序告诉他时你会怎么回应? “你的名字无效”?

根据你真正想要实现的目标,你可以考虑使用某种黑名单/过滤器来排除你想到的“非名字”:它可能会让一些“坏名字”通过,但是,至少,它不应该阻止任何现有名称访问您的应用程序。

以下是一些可以想到的规则示例:

  • 没有号码
  • 没有特殊字符,例如"~{()}@^$%?;:/*§£ø,可能还有其他一些
  • 不再有3个空格?
  • 没有“管理员”,“支持”,“主持人”,“测试”以及人们在不想输入真实姓名时往往会使用的其他一些明显的非名字......
    • (但是,如果他们不想给你他们的名字,他们仍然不会,即使你禁止他们输入一些随机字母,他们也可以只使用一个真实姓名......这不是他们的名字)

是的,这并不完美;是的,它会让一些非名字传递......但是对你的应用来说可能比说“你的名字错了”更好(是的,我坚持^^)


并且,回答你留下的评论:

  

我可以禁止最多的命令   SQL注入和XSS的字符   攻击,

关于SQL注入,您必须在将数据发送到数据库之前将其转义;并且,如果你总是逃避这些数据(你应该!),你不必关心用户可能输入的内容:因为它被转义,所以总是存在风险。

相同的XSS:因为你总是在输出数据时逃避你的数据(你应该!),没有注入的风险; - )


编辑:如果你只是使用那样的正则表达式,它将无法正常工作:

以下代码:

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

至少会给你一个警告:

Warning: preg_match() [function.preg-match]: Unknown modifier '{'

你必须逃脱至少一些特殊的角色;我会让你深入研究PCRE Patterns以获取更多信息(关于PCRE /正则表达式真的有很多了解;我将无法解释所有这些)

如果您确实想要检查这些字符中是否存在这些字符,那么最终可能会出现类似的情况:

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

(这是一个快速而肮脏的主张,必须加以完善!)

这个人说“OK”(好吧,我肯定希望我自己的名字没问题!)
和一些特殊字符相同的例子,如下:

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'ma{rtin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

会说“坏名声”

但请注意我对此进行了全面测试,可能需要更多工作!除非您经过仔细测试,否则请勿在您的网站上使用此功能!


另请注意,在尝试执行SQL注入时,单引号可能会有所帮助......但它可能是某些名称中合法的字符...因此,仅排除某些字符可能是不够的; - )

答案 1 :(得分:6)

PHP’s PCRE implementation支持跨越更多字符的Unicode character properties。因此,您可以使用\p{L}(字母字符),\p{P}(标点字符)和\p{Zs}(空格分隔符)的组合:

/^[\p{L}\p{P}\p{Zs}]+$/

但是可能会有这些字符类别未涵盖的字符,而可能包含一些您不希望被允许的字符。

因此,我建议您不要在数据上使用正则表达式,这些表达式具有如此模糊的值范围,例如真实姓名。


编辑在编辑问题时,现在看到您只想防止某些代码注入攻击:您应该更好地逃避这些角色,而不是将其作为潜在的攻击企图拒绝。

使用mysql_real_escape_stringprepared statements进行SQL查询,使用htmlspecialchars进行HTML输出,并使用其他语言的其他适当函数。

答案 2 :(得分:4)

这是一个没有简单通用解决方案的问题。问题是你真的无法预测名称可能包含的字符。可能最好的解决方案是定义一个负面的字符掩码,以排除一些你真的不希望以名字结尾的特殊字符。

您可以使用以下方式执行此操作:

$ regexp =“/ ^ [ ^ &lt;把不需要的字符放在这里&gt; ] + $ /

答案 3 :(得分:2)

如果您尝试在PHP中解析人名,我建议Keith Beckman's nameparse.php script