40 votes

Expression régulière pour la validation des noms et prénoms ?

Bien que cette question semble triviale, je suis certain qu'elle ne l'est pas :)

Je dois valider les noms et prénoms de personnes du monde entier. Imaginez une énorme liste de millions de noms et de prénoms dans laquelle je dois supprimer le mieux possible tout ce que j'identifie. Comment puis-je faire cela avec une expression régulière ? S'il ne s'agissait que de noms anglais, je pense que cela suffirait :

^[a-z -']+$

Cependant, je dois également soutenir ces cas :

  • d'autres symboles de ponctuation tels qu'ils peuvent être utilisés dans différents pays (je ne sais pas lesquels, mais peut-être le savez-vous !)
  • différents jeux de lettres Unicode (lettres accentuées, grecques, japonaises, chinoises, etc.)
  • pas de chiffres ou de symboles ou de ponctuation inutile ou de runes, etc.
  • les titres, les initiales intermédiaires, les suffixes ne font pas partie de ces données
  • Les noms sont déjà séparés par des noms de famille.
  • nous sommes prêts à forcer les noms ultra rares à être simplifiés (il existe une personne nommée '@', mais il n'est pas logique d'autoriser ce caractère partout. Faites preuve de pragmatisme et de bon sens).
  • Notez que de nombreux pays ont des lois sur les noms et qu'il existe donc des normes à respecter.

Existe-t-il une méthode standard de validation de ces champs que je peux mettre en œuvre pour m'assurer que les utilisateurs de notre site Web bénéficient d'une expérience agréable et qu'ils peuvent effectivement utiliser leur nom lors de l'inscription dans la liste ?

Je chercherais quelque chose de similaire aux nombreuses regex "adresse électronique" que l'on peut trouver sur Google.

2 votes

Je doute que cela soit faisable - il y a trop de symboles Unicode pour exclure tous les symboles indésirables (et comment vous dire quels symboles chinois exclure ?) et il y a certainement trop de symboles valides pour les inclure tous (et vous aurez à nouveau le problème des symboles chinois). Je ne mettrais aucune contrainte sur un nom d'utilisateur - il peut même contenir des chiffres ; pensez aux noms aristocratiques.

9 votes

kalzumeus.com/2010/06/17/… Vous devriez lire attentivement ce qui suit.

0 votes

Peut-être cette regex : [[:alpha:]-]/u

44voto

Chris Cudmore Points 11133

Je comprends la nécessité de limiter l'entrée dans cette situation, mais je ne pense pas que ce soit possible - Unicode est vaste, en pleine expansion, tout comme le sous-ensemble utilisé dans les noms du monde entier.

Contrairement au courrier électronique, il n'y a pas de norme universellement reconnue pour les noms que les gens peuvent utiliser, ni même pour les représentations qu'ils peuvent enregistrer comme officielles auprès de leurs gouvernements respectifs. Je soupçonne que n'importe quelle regex finira par ne pas passer un nom considéré comme valide par quelqu'un , quelque part dans le monde.

Bien sûr, vous devez assainir ou échapper les entrées, afin d'éviter la Tables Little Bobby problème. Et il peut y avoir d'autres contraintes sur les entrées que vous autorisez également, comme les systèmes sous-jacents utilisés pour stocker, rendre ou manipuler les noms. En tant que tel, je vous recommande de déterminer d'abord les restrictions imposées par le système auquel appartient votre validation, et de créer une expression de validation basée uniquement sur celles-ci. Cela peut encore causer des désagréments dans certains scénarios, mais ils devraient être rares.

15 votes

En fait, j'autoriserais Bobby à entrer son nom ; je m'assurerais simplement qu'il est échappé avant de l'envoyer à la base de données. De même, j'autoriserais M. "><script>alert("XSS");//</script à entrer son nom, et je l'échapperais avant de l'envoyer au navigateur. Je n'assainirais l'entrée que si je pensais que mes collègues pourraient se tromper dans l'échappement.

7 votes

@Skliwz - Alors c'est ce que vous devez faire. S'ils n'échappent pas correctement lors de l'insertion dans SQL, tout nom avec une apostrophe (que votre question originale reconnaît déjà comme nécessaire) vous ouvre à des vulnérabilités de sécurité. Imaginez que vous essayez d'authentifier un utilisateur nommé "Foo'or True Or'foo" - pas de caractères "dangereux", mais c'en est fini de votre schéma de connexion.

1 votes

Si tout ce que vous faites est de lire et d'écrire dans la base de données, le paramétrage correct des requêtes devrait résoudre le problème. Cependant, si vous devez exécuter dynamiquement du code à partir de la base de données, vous devez faire attention (par exemple en utilisant l'instruction exec()).

17voto

Sklivvz Points 16412

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, l'apostrophe et le trait d'union. Je n'ai vu aucun autre cas dans la liste des cas limites.

En ce qui concerne les chiffres, il n'y a qu'un seul cas avec un 8. Je pense que je peux l'interdire sans risque.

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

Je veux aussi inclure l'espace.

Cela se résume à cette regex :

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

Cela présente un problème, à savoir que l'apostrophe peut être utilisée comme vecteur d'attaque. Elle devrait être codée.

Le code de validation devrait donc être quelque chose comme ceci (non testé) :

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

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


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);
            }
        }
    }
}

22 votes

Désolé, vous allez quand même laisser des noms valides en plan. Je vous suggère fortement de vous documenter sur les diacritiques en arabe, notamment ceux qui sont des caractères Unicode distincts mais qui se combinent aux lettres pour les modifier. Allez-vous interdire des noms comme "John W. Saunders, 3rd" ? J'espère que non. Le monde est bien plus vaste que vous ne semblez l'imaginer, et vos règles simplistes, orientées vers l'Occident, ne fonctionneront tout simplement pas en général.

4 votes

Bonjour John, la regex supporte les diacritiques (l'arabe est aussi dans les cas de test) avec l'attribut \p {M}. De plus, je ne valide que les noms, c'est-à-dire que dans votre exemple, il s'agirait de "John W.". (ou "John" et "W.") et "Saunders". "," ne fait pas partie du nom et "3ème" est un suffixe.

0 votes

Vous vous attendez à ce que les utilisateurs saisissent FirstName, LastName, Suffix ????. Ou bien vous aurez également Préfixe, Milieu du nom1, Milieu du nom2 .... Il existe une autre question sur les noms qui traite de ces problèmes de manière approfondie.

15voto

user9876 Points 5385

J'autoriserais tout (sauf une chaîne vide) et supposerais que l'utilisateur sait quel est son nom.

Il y a 2 cas courants :

  1. Vous vous assurez que le nom est exact et vous le comparez à un passeport en papier ou à un autre document d'identité, ou encore à une carte de crédit.
  2. Vous ne vous en souciez guère et l'utilisateur pourra de toute façon 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 par rapport à un document papier.

Dans le cas (2), on peut tout aussi bien autoriser tous les caractères, car "123 456" n'est pas vraiment un pseudonyme plus mauvais que "Abc Def".

4 votes

+1 L'utilisation d'une regex garantit uniquement que l'entrée correspond à la regex, elle ne vous dira pas s'il s'agit d'un nom valide.

0 votes

Y a-t-il des noms avec des emojis ?

0 votes

@Cœur AFAIK pas encore, mais un parent "branché" finira bien par l'infliger à son enfant...

13voto

kscott Points 912

Je pense que vous seriez mieux à l'exclusion de les caractères que vous ne voulez pas avec une regex. Essayer d'obtenir chaque tréma, e accentué, trait d'union, etc. sera assez insensé. Excluez simplement les chiffres (mais qu'en est-il d'un type nommé "George Forman le 4ème") et les symboles que vous savez ne pas vouloir comme @#$%^ ou autre. Mais même dans ce cas, l'utilisation d'une regex ne fera que garantir que l'entrée correspond à la regex, elle ne vous dira pas si le nom est valide.

EDIT après avoir précisé qu'il s'agit d'une tentative de prévention du XSS : Une regex sur un champ de nom ne va évidemment pas empêcher le XSS à elle seule. Toutefois, cet article contient une section sur le filtrage qui constitue un point de départ si vous souhaitez emprunter cette voie.

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

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

1 votes

En dehors de la désinfection de l'entrée, je ne vois pas de raison d'éliminer des caractères. Qu'essayez-vous d'empêcher ?

0 votes

Tous les caractères dont on peut être sûr qu'ils ne finiront pas dans un nom. Puisque les gens peuvent vraiment être nommés de n'importe quoi, rien n'est sûr dans une certaine mesure. Mais je pense que les exemples donnés par kscott !@#$%^ sont un bon point de départ. Vous pourriez facilement faire passer une grande liste de noms dans votre expression lorsque vous aurez terminé et voir ce qui en ressort (le cas échéant). +1

1 votes

Aucune regex n'empêchera une attaque de type "cross site scripting".

6voto

Gumbo Points 279147

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 des caractères Unicode), cela n'empêcherait pas les utilisateurs d'entrer des pseudo-noms comme John Doe , Max Mustermann (il existe même une personne portant ce nom), Abcde Fghijk o Ababa Bebebe .

0 votes

Si vous voulez imprimer l'entrée de l'utilisateur dans un document HTML, échappez le caractère méta HTML ( & , < , > , " y ' ). Si vous souhaitez imprimer l'entrée de l'utilisateur dans une déclinaison de chaîne JavaScript, échappez les métacaractères de la chaîne JavaScript ( `, " et ' ). Si vous souhaitez imprimer l'entrée de l'utilisateur dans une déclaration de chaîne JavaScript à l'intérieur d'un document HTML, échappez d'abord les métacaractères de la chaîne JavaScript, puis les métacaractères HTML. Si vous souhaitez utiliser l'entrée utilisateur dans une déclaration de chaîne SQL, échappez les métacaractères de la chaîne SQL. Vous voyez le schéma ?

4 votes

C'est à VOUS de le faire du côté du serveur et non du côté du client. N'oubliez pas : Ne faites jamais confiance aux données des utilisateurs !

4 votes

Il semble que vous n'ayez pas compris ce qu'est exactement le XSS ni son défaut fondamental. Il s'agit de passer d'un contexte, dans lequel une certaine valeur est considérée comme sûre, à un autre, dans lequel la même valeur n'est pas considérée comme sûre. Et ce changement est initié par la valeur elle-même, car elle contient des séquences de caractères particulières qui marquent la fin d'un contexte et le début de l'autre. Tout comme le " marque la fin/le début d'une déclaration de chaîne de caractères. Maintenant, si vous voulez placer une chaîne dans une autre déclaration de chaîne, vous devez échapper ces séquences de caractères pour qu'elles soient traitées comme des littéraux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X