web-dev-qa-db-fra.com

Expression régulière pour valider les noms et prénoms?

Bien que cela semble une question triviale, je suis tout à fait sûr que ce n’est pas le cas :)

Je dois valider les noms et prénoms de personnes de partout dans le monde. Comment puis-je faire cela avec une expression régulière? Si c'étaient des anglais, je pense que cela suffirait:

^[a-z -']+$

Cependant, je dois également supporter ces cas:

  • autres symboles de ponctuation tels qu'ils pourraient être utilisés dans différents pays (aucune idée de quoi, mais peut-être que vous l'êtes!)
  • différents jeux de lettres Unicode (lettre accentuée, grec, japonais, chinois, etc.)
  • pas de chiffres ni de symboles, ni ponctuation inutile, ni runes, etc.

Existe-t-il un moyen standard de valider ces champs que je peux mettre en œuvre pour que les visiteurs de notre site Web aient une bonne expérience et puissent utiliser leur nom lors de leur inscription?

Je chercherais quelque chose de similaire aux nombreux regex "adresse email" que vous pouvez trouver sur google.

37
Sklivvz

Je vais essayer de donner une réponse appropriée moi-même:

Les seules ponctuations qui devraient être autorisées dans un nom sont le point final, l'apostrophe et le trait d'union. Je n'ai vu aucun autre cas dans la liste des cas de coin.

En ce qui concerne les chiffres, il n'y a qu'un seul cas avec un 8. Je pense pouvoir le refuser en toute sécurité.

En ce qui concerne les lettres, toute lettre est valide.

Je veux aussi inclure de l'espace.

Cela résumerait cette regex:

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

Cela pose un problème, c’est-à-dire que l’apostrophe peut être utilisée comme vecteur d’attaque. Il devrait être encodé.

Le code de validation devrait donc ressembler à ceci (non testé):

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

Quelqu'un peut-il penser à une raison pour laquelle un nom ne devrait pas réussir ce test ou une injection XSS ou SQL qui pourrait réussir?


solution complète testée

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

En fait, je ne me dérangerais pas. 

Peu importe la regex que vous proposez, je peux trouver un nom quelque part dans le monde qui le brisera.

Cela étant dit, vous devez assainir les entrées pour éviter le problème de Little Bobby Tables .

41
Chris Cudmore

Je voudrais juste tout autoriser (sauf une chaîne vide) et supposer que l'utilisateur sait quel est son nom.

Il y a 2 cas communs:

  1. Vous vous assurez que le nom est exact et que vous le validez contre un vrai passeport en papier ou un autre document d’identité, ou avec une carte de crédit.
  2. Cela vous est bien égal et l'utilisateur pourra quand même s'inscrire en tant que "Fred Smith" (ou "Jane Doe").

Dans le cas (1), vous pouvez autoriser tous les caractères car vous effectuez une vérification sur un document papier.

Dans le cas (2), vous pouvez également autoriser tous les caractères car "123 456" n’est pas pire un pseudonyme que "Abc Def".

15
user9876

Je penserais que vous seriez mieux lotis excluant les caractères que vous ne voulez pas avec une regex. Essayer d'obtenir chaque tréma, accentué e, trait d'union, etc. sera assez fou. Excluez simplement les chiffres (mais qu’en est-il du type "George Forman the 4th") et des symboles que vous savez ne pas vouloir, par exemple @ # $% ^? Mais même dans ce cas, utiliser une expression régulière garantira uniquement que l'entrée correspond à l'expression régulière, cela ne vous dira pas qu'il s'agit d'un nom valide.

EDIT après avoir clarifié qu'il s'agissait d'empêcher XSS: Une regex sur un champ de nom ne va évidemment pas arrêter XSS seul. Cependant, cet article contient une section sur le filtrage qui constitue un point de départ si vous souhaitez suivre cette voie.

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

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

Je ne pense pas que ce soit une bonne idée. Même si vous trouvez une expression régulière appropriée (peut-être en utilisant les propriétés de caractère Unicode), cela n'empêcherait pas les utilisateurs d'entrer des pseudo-noms tels que John Doe , Max Mustermann (il y a même une personne portant ce nom ), Abcde Fghijk ou Ababa Bebebe .

6
Gumbo

BTW, envisagez-vous d'autoriser uniquement l'alphabet latin, ou envisagez-vous également de valider le chinois, l'arabe, l'hindi, etc.?

Comme d'autres l'ont déjà dit, n'essayez même pas de faire {essayer} _. Reculez et demandez-vous ce que vous essayez réellement d'accomplir. Ensuite, essayez de le réaliser sans faire de suppositions sur le nom ou le sens des noms.

6
John Saunders

Vous pouvez utiliser le code de regex suivant pour valider 2 noms séparés par un espace avec le code de regex suivant:

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

ou simplement utiliser:

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

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

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

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

6
Paulo Carvalho

Un sujet très controversé que je semble avoir trébuché ici. Cependant, il est parfois agréable de laisser tomber les tables de passe-passe et d'envoyer le petit Robert au bureau du directeur avec ses points-virgules et ses commentaires SQL -.

Ce REGEX en VB.NET comprend des caractères alphabétiques normaux et divers caractères européens circonflexés. Cependant, le pauvre vieux James Mc’Tristan-Smythe III devra inscrire son pedigree dans le rôle de Jim the Third.

<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

Il est très difficile de valider quelque chose comme un nom en raison de tous les cas possibles.

Coins

Désinfectez les entrées et laissez-les entrer ce qu'elles veulent comme nom, car le choix d'un nom valide ou non dépend probablement du cadre que vous choisissez; compte tenu de la gamme de potentiels noms étranges - et légaux est presque infini.

S'ils veulent s'appeler Tricyclopltz ^ 2-Glockenschpiel, c'est leur problème, pas le vôtre.

2
Trampas Kirk

Pas: 

  1. d'abord supprimer tous les accents 
  2. appliquer l'expression régulière

Pour enlever les accents:

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