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:
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.
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("'", "'");
Console.WriteLine(name);
}
}
}
}
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 .
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:
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".
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;
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 .
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.
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À-ú] + $
[[: lower:]] = [a-zà-ú]
[[: upper:]] = [A-ZÀ-Ú]
[[: alpha:]] = [A-Za-zÀ-ú]
[[: alnum:]] = [A-Za-zÀ-ú0-9]
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}\']+$">
Il est très difficile de valider quelque chose comme un nom en raison de tous les cas possibles.
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.
Pas:
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();
}