web-dev-qa-db-ja.com

名前と姓を検証するための正規表現?

これは些細な質問のように思えますが、そうではないと確信しています:)

世界中の人々の名前と姓を検証する必要があります。どうすれば正規表現でそれを行うことができますか?もしそれが英語のものだけなら、これはそれを減らすだろうと思います:

^[a-z -']+$

ただし、これらのケースもサポートする必要があります。

  • さまざまな国で使用される可能性のある他の句読記号(どれかはわかりませんが、多分そうです!)
  • さまざまなUnicode文字セット(アクセント付き文字、ギリシャ語、日本語、中国語など)
  • 数字や記号、不必要な句読点やルーン文字などはありません。

これらのフィールドを検証して、Webサイトの訪問者が素晴らしい体験をし、実際に登録時に名前を使用できるようにするための標準的な方法はありますか?

私はあなたがグーグルで見つけることができる多くの「電子メールアドレス」正規表現に似た何かを探しているでしょう。

39
Sklivvz

私は自分で適切な答えをしようとします:

名前に使用できる句読点は、フルストップ、アポストロフィ、ハイフンのみです。コーナーケースのリストに他のケースはありません。

数字に関しては、8のケースは1つしかありません。それを安全に拒否できると思います。

手紙に関しては、どんな手紙も有効です。

スペースも含めたいです。

これはこの正規表現に要約されます:

^[\p{L} \.'\-]+$

これには1つの問題があります。つまり、アポストロフィは攻撃ベクトルとして使用できます。エンコードする必要があります。

したがって、検証コードは次のようになります(テストされていません)。

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

誰も名前がこのテストまたは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);
            }
        }
    }
}
18
Sklivvz

私は実際に気にしません。

あなたがどんな正規表現を思いついたとしても、私はそれを破る世界のどこかに名前を見つけることができます。

そうは言っても、 Little Bobby Tables の問題を回避するには、入力をサニタイズする必要があります。

41
Chris Cudmore

すべてを許可し(空の文字列を除く)、ユーザーが自分の名前を知っていると仮定します。

2つの一般的なケースがあります。

  1. 名前が正確であり、実際の紙のパスポートまたはその他の身分証明書、またはクレジットカードに対して検証していることに注意してください。
  2. あなたはそれほど気にしなくても、ユーザーは「フレッド・スミス」(または「ジェーン・ドゥー」)として登録できます。

(1)の場合、紙の文書と照合するため、すべての文字を許可できます。

(2)の場合、「123 456」は実際には「Abc Def」よりも偽名ではないため、すべての文字を許可することもできます。

15
user9876

除外正規表現では不要な文字を使用した方が良いと思います。すべてのウムラウト、アクセント付きe、ハイフンなどを取得しようとすると、かなり狂気になります。数字を除外します(ただし、「George Forman the 4th」という名前の人はどうでしょうか)。しかし、それでも、正規表現を使用すると、入力が正規表現と一致することのみが保証され、有効な名前であることは通知されません

これがXSSを防止しようとしていることを明確にした後に編集します:名前フィールドの正規表現は、XSS自体を明らかに停止しません。ただし、この記事には、そのルートに進みたい場合の出発点となるフィルタリングに関するセクションがあります。

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

s/[\<\>\"\'\%\;\(\)\&\+]//g;
11
kscott

それは良い考えだとは思いません。適切な正規表現(Unicode文字プロパティを使用している場合があります)を見つけたとしても、ユーザーがJohn DoeMax Mustermann(その名前の人)、Abcde FghijkまたはAbaba Bebebe

6
Gumbo

ところで、ラテンアルファベットのみを許可する予定ですか、それとも中国語、アラビア語、ヒンディー語などを検証しようとする予定ですか?

他の人が言ったように、tryでさえしないでください。一歩下がって、あなたが実際に達成しようとしていることを自問してください。次に、人々の名前が何であるか、または彼らが何を意味するかについての仮定をせずにそれを達成しようとします。

6
John Saunders

次の正規表現コードを使用して、スペースで区切られた2つの名前を次の正規表現コードで検証できます。

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

または単に使用する:

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

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

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

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

6
Paulo Carvalho

私がここで偶然見つけたように思える非常に論争的な主題。しかし、パスで親愛なる小さなボビーのテーブルを離れ、セミコロンとSQLコメント行とともに小さなロバートを校長室に送るのはいいことです。

VB.NETのこのREGEXには、通常のアルファベット文字とさまざまな曲折ヨーロッパ文字が含まれています。しかし、貧しい年老いたジェームズ・マクトリスタン・スマイス3世は、ジム3世として彼の血統を入力する必要があります。

<asp:RegularExpressionValidator ID="RegExValid1" Runat="server"
                    ErrorMessage="ERROR: Please enter a valid surname<br/>" SetFocusOnError="true" Display="Dynamic"
                    ControlToValidate="txtSurname" ValidationGroup="MandatoryContent"
                    ValidationExpression="^[A-Za-z'\-\p{L}\p{Zs}\p{Lu}\p{Ll}\']+$">
2
Timi

名前のようなものを検証することは非常に難しい問題であり、可能な限りすべてのケースがあります。

コーナーケース

入力をサニタイズし、名前に必要なものは何でも入力できるようにします。これは、有効な名前とそうでないものを決定するのは、おそらくあなたがしていることの範囲外だからです。潜在的な奇妙な範囲を考えると、正式な名前はほぼ無限です。

彼らが自分自身をTricyclopltz ^ 2-Glockenschpielと呼びたいなら、それはあなたの問題ではなく彼らの問題です。

2
Trampas Kirk

これはJavaScriptで完璧に機能しました^ [a-zA-Z] + [\ s |-]?[a-zA-Z] + [\ s |-]?[a-zA-Z] + $

メソッドは次のとおりです。

function isVallidName(name) {
    var found = name.search(/^[a-zA-Z]+[\s|-]?[a-zA-Z]+[\s|-]?[a-zA-Z]+$/);
    if(found > -1) {
        return true;
    }
    else {
        return false;
    }
}
1
user2288580

手順:

  1. 最初にすべてのアクセントを削除します
  2. 正規表現を適用する

アクセントを取り除くには:

private static string RemoveAccents(string s)
{
    s = s.Normalize(NormalizationForm.FormD);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.Length; i++)
    {
        if (CharUnicodeInfo.GetUnicodeCategory(s[i]) != UnicodeCategory.NonSpacingMark) sb.Append(s[i]);
    }
    return sb.ToString();
}
0
Martin Staufcik