用于验证姓名和姓氏的正则表达式?

Skl*_*vvz 38 c# regex globalization

虽然这看起来像一个微不足道的问题,但我很确定它不是:)

我需要验证来自世界各地的人的姓名和姓氏.我怎么能用正则表达式做到这一点?如果它只是英文版,我认为这会削减它:

^[a-z -']+$
Run Code Online (Sandbox Code Playgroud)

但是,我还需要支持这些案例:

  • 其他标点符号,因为它们可能在不同国家使用(不知道哪个,但也许你这样做!)
  • 不同的Unicode字母集(重音字母,希腊语,日语,中文等)
  • 没有数字或符号或不必要的标点符号或符文等.

有没有一种标准方法来验证我可以实现的这些字段,以确保我们的网站访问者有一个很好的经验,并可以在注册时实际使用他们的名字

我会寻找类似于你可以在谷歌上找到的许多"电子邮件地址"正则表达式的东西.

Chr*_*ore 42

我其实不会打扰.

无论你想出什么样的正则表达式,我都可以在世界某个地方找到一个可以打破它的名字.

话虽这么说,你确实需要清理输入,以避免Little Bobby Tables问题.

  • 其实我允许鲍比输入他的名字; 我只是确保它在我发送到数据库之前被转义.同样地,我允许Mr>> <script> alert("XSS"); // </ script>来获得他的名字,并且在将它发送到浏览器之前我将其转义.我只会清理输入如果我认为我的同事可能搞砸了逃跑. (15认同)
  • @Skliwz - 那就是你需要解决的问题.如果在插入SQL时它们没有正确转义,任何带有撇号的名称(您的原始问题已经在必要时已经识别出来)会让您面临安全漏洞.想象一下,尝试验证名为"Foo'or True Or'foo"的用户 - 没有"危险"字符,但是你的登录方案就是这样. (7认同)
  • @ PatrickBrinich-Langlois:一切都很好,直到您不能因此登上飞机或进行银行转账(由于撇号处理不当,这两种情况都发生在我身上)。 (4认同)
  • 我认为每个网站必须包含所有可能名称的假设都是错误的.有奇怪名字的人习惯于无法在任何地方使用它们.我的姓氏太长,不适合许多信用卡和政府表格,所以我只是截断它.通常连字符被删除.没什么大不了的.我正在处理的应用程序现在每月有一千个用户在注册时在名字或姓氏字段中输入电子邮件地址.有些人可能在他们的名字中合法地使用"@",但这个数字与那些只是犯错误的数字相比微不足道. (3认同)

Skl*_*vvz 16

我会试着给自己一个正确的答案:

名称中唯一允许的标点符号是句号,撇号和连字符.在角落案件清单中我没有看到任何其他案例.

关于数字,只有一个案例有8个.我想我可以安全地拒绝这个.

关于信件,任何信件都是有效的.

我也想要包括空间.

这将总结到这个正则表达式:

^[\p{L} \.'\-]+$
Run Code Online (Sandbox Code Playgroud)

这提出了一个问题,即撇号可以用作攻击向量.它应该编码.

所以验证代码应该是这样的(未经测试):

var name = nameParam.Trim();
if (!Regex.IsMatch(name, "^[\p{L} \.\-]+$")) 
    throw new ArgumentException("nameParam");
name = name.Replace("'", "&#39;");  //&apos; does not work in IE
Run Code Online (Sandbox Code Playgroud)

任何人都可以想到一个名称不应该通过此测试或可以通过的XSS或SQL注入的原因吗?


完整测试解决方案

using System;
using System.Text.RegularExpressions;

namespace test
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var names = new string[]{"Hello World", 
                "John",
                "João",
                "???",
                "???",
                "??",
                "??",
                "??????",
                "????????",
                "?????????",
                "???? ?????",
                "?????????",
                "??????",
                "?",
                "D'Addario",
                "John-Doe",
                "P.A.M.",
                "' --",
                "<xss>",
                "\""
            };
            foreach (var nameParam in names)
            {
                Console.Write(nameParam+" ");
                var name = nameParam.Trim();
                if (!Regex.IsMatch(name, @"^[\p{L}\p{M}' \.\-]+$"))
                {
                    Console.WriteLine("fail");
                    continue;
                }
                name = name.Replace("'", "&#39;");
                Console.WriteLine(name);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对不起,你仍然会在寒冷中留下有效的名字.我强烈建议你阅读阿拉伯语中的变音符号,特别是那些单独的Unicode字符,但它们与字母组合以改变它们.你会不会不喜欢"John W. Saunders,3rd"这样的话吗?我希望不是.它只是一个比你似乎意识到的更广阔的世界,而你的简单化,西方化的规则根本不会起作用. (22认同)
  • 来自Saint-Louis-du-Ha的人们!_Ha!会不高兴.http://en.wikipedia.org/wiki/Saint-Louis-du-Ha!_Ha!,_Quebec (7认同)
  • [श्रीखनाल对你不满意.](http://meta.stackexchange.com/questions/171814/display-name-in-local-language)说真的,请阅读http://www.kalzumeus.com/2010/ 06/17/falsehoods-programsmers-believe-about-names /和你的信念交换[saner](http://stackoverflow.com/a/888902) [方法](http://stackoverflow.com/a/ 888870). (5认同)
  • 嗨约翰,正则表达式支持变音符号(阿拉伯语也在测试用例中)与\ p {M}.而且,我只是验证名称,即在你的例子中那些将是"John W." (或"约翰"和"W")和"桑德斯".","不是名称的一部分,"3rd"是后缀. (4认同)

use*_*876 15

我只会允许所有内容(除了空字符串)并假设用户知道他的名字是什么.

有两种常见情况:

  1. 您关心的是该名称是准确的,并且是针对真实纸质护照或其他身份证件或信用卡进行验证的.
  2. 您并不在乎这一点,用户无论如何都可以注册为"Fred Smith"(或"Jane Doe").

在情况(1)中,您可以允许所有字符,因为您正在检查纸质文档.

在情况(2)中,您也可以允许所有字符,因为"123 456"实际上并不比"Abc Def"更糟糕.

  • +1 - 世界上没有正则表达式匹配颠覆意图. (4认同)
  • +1使用正则表达式只能保证输入与正则表达式匹配,它不会告诉您它是一个有效的名称 (4认同)

ksc*_*ott 13

我认为你最好用正则表达式排除你不想要的字符.试图获得每个变音,重音e,连字符等将是非常疯狂的.只是排除数字(但那么一个名为"George Forman the 4th"的人)和你知道你不想要的符号就像@#$%^或者你有什么.但即便如此,使用正则表达式只能保证输入与正则表达式匹配,它不会告诉你它是一个有效的名字

编辑后澄清这是试图阻止XSS: 名称字段上的正则表达式显然不会自行阻止XSS.但是,本文有一个关于过滤的部分,如果你想要走这条路线,这是一个起点.

http://tldp.org/HOWTO/Secure-Programs-HOWTO/cross-site-malicious-content.html

s/[\<\>\"\'\%\;\(\)\&\+]//g;
Run Code Online (Sandbox Code Playgroud)


Joh*_*ers 7

顺便说一下,你打算只允许使用拉丁字母,还是打算尝试验证中文,阿拉伯语,印地语等?

正如其他人所说,甚至不尝试这样做.退后一步,问问自己你实际想要完成什么.然后尝试完成它,而不做任何关于人们姓名或者他们的意思的假设.

  • 因为验证名称不是防止跨站点脚本的方式.你允许用户在字段中放置他们想要的东西,因为名字很疯狂,世界上有很多unicode字符,那么你就可以对待任何放在该领域的人,就像放射性一样. (9认同)
  • 试着做什么?你知道用这些语言命名的规则吗?你知道如何区分这些语言中的名字和姓氏吗?不要解析名字 - 只要接受人们知道他们的名字. (2认同)

Gum*_*mbo 6

我认为这不是一个好主意.即使你找到一个合适的正则表达式(可能使用Unicode字符属性),这也不会阻止用户输入像John Doe,Max Mustermann(甚至有一个有这个名字的人),Abcde FghijkAbaba Bebebe这样的伪名字.

  • 在服务器端而不是客户端上执行此操作是您的工作.记住:永远不要相信用户数据! (4认同)
  • 嗯,似乎你不明白XSS到底是什么,或者它的根本缺陷是什么.它从一个被认为是安全的上下文转变为另一个被认为是安全的上下文.并且该更改由值本身启动,因为它包含标记一个结束的特定字符序列和另一个上下文的开头.就像```标记字符串声明的结束/开始一样.现在如果你想将字符串放入另一个字符串declration中,你需要转义那些字符序列以使它们被视为文字. (4认同)
  • 您只需要转义上下文元字符. (3认同)

小智 5

您可以使用以下正则表达式代码验证由空格分隔的2个名称,并使用以下正则表达式代码:

^ [A-Za-zÀ-ú] + [A-Za-zÀ-ú] + $

或者只是使用:

[[:lower:]] = [a-zà-ú]

[[:upper:]] = [A-ZÀ-Ú]

[[:alpha:]] = [A-Za-zÀ-ú]

[[:alnum:]] = [A-Za-zÀ-ú0-9]

  • 这个正则表达式会遗漏像"Laura E. Ingalls"或"Laura Elisabeth Ingalls Wilder"或"Laura Elisabeth Ingalls-Wilder". (4认同)