我在用于人类姓名的正则表达式方面遇到了一些问题。

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

假设一个名为 Jürgen 的用户想要注册?还是鲍勃?这在欧洲很常见。这有特殊的注释吗?

编辑:,刚刚将 Jürgen 名字扔给正则表达式创建者,它在 ü 字母处将单词分开......

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

编辑2:好吧,既然检查这些特定的东西很困难,为什么不使用简单地检查非法字符的正则表达式呢?

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

(现在其中哪些实际上可以用于任何黑客尝试?)

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

有帮助吗?

解决方案

我真的想说:不要尝试验证名称:有一天或有一天,你的代码会遇到一个它认为“错误”的名称......当应用程序告诉他时,你认为人们会如何反应“你的名字无效" ?

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

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

  • 没有号码
  • 没有特殊字符,例如 "~{()}@^$%?;:/*§£ø 可能还有其他一些
  • 不超过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模式 了解更多信息 (关于 PCRE / regex 确实有很多东西需要了解;我无法解释这一切)

如果您确实想检查给定数据中是否没有这些字符,您可能会得到类似的结果:

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

(这是一个快速而肮脏的提议,必须加以改进!)

这个说“好的” (好吧,我绝对希望我自己的名字没问题!)
还有一些特殊字符的相同示例,如下所示:

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

会说“坏名字”

但请注意我有 不是 对此进行了充分测试,可能需要更多工作!除非您非常仔细地测试过,否则不要在您的网站上使用它!


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

其他提示

PHP 的 PCRE 实现 支持 Unicode 字符属性 跨越更大的字符集。所以你可以结合使用 \p{L} (字母字符), \p{P} (标点符号)和 \p{Zs} (空格分隔符):

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

但可能有些字符不属于这些字符类别,而有些字符可能是您不希望被允许的。

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


编辑当您编辑问题时,现在发现您只想防止某些代码注入攻击:您应该更好地逃避这些字符,而不是拒绝它们作为潜在的攻击尝试。

使用 mysql_real_escape_string 或者 准备好的陈述 对于 SQL 查询, htmlspecialchars 用于 HTML 输出和其他语言的其他适当功能。

这是一个没有简单通用解决方案的问题。问题是您确实无法预测名称可能包含哪些字符。也许最好的解决方案是定义一个负字符掩码来排除一些您确实不希望出现在名称中的特殊字符。

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

$正则表达式=“/^[^<在此放置不需要的字符>]+$/

如果你试图解析除了人的名字在PHP中,我电子书籍的基思Beckman的nameparse.php脚本

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top