Adresse e-mail en tant que nom d'user BUG

Je développe un site Web MVC4 avec une database SQL Server. Je veux save des personnes avec leur adresse email.

Toutefois, si l'adresse électronique contient le caractère i , la méthode WebSecurity.CreateUserAndAccount lève une exception:

Le fournisseur d'authentification a renvoyé une erreur. Veuillez vérifier votre input et réessayer. Si le problème persiste, contactez votre administrateur système.

J'ai beaucoup étudié et trouvé quelques articles à ce sujet, mais il n'y a pas de solution.

http://forums.asp.net/t/1862233.aspx/1?How+can++++address+address+for+username+in+MVC4+Membership

http://aspnetwebstack.codeplex.com/workitem/714

Votre problème fondamental est que vous essayez d'entrer des caractères non ASCII en tant qu'adresse de messagerie.

Le "jeu de caractères ASCII" vous limite à l'alphabet US-anglais, qui se trouve être l'alphabet latin.

Je ne parle pas turc, mais comme indiqué dans http://aspnetwebstack.codeplex.com/workitem/714

En turc, «i» est en minuscule, tandis que «İ» est supérieur à «i».
Dans l'alphabet latin, que vous (et moi) ne possédez pas, IT est en minuscule, tandis que «I» est majuscule de i.

Vous avez donc un caractère qui n'est pas membre du jeu de caractères ASCII EN-US.
Par conséquent, le paramètre de classment vous empêche d'entrer des caractères non ASCII dans votre database, d'où l'erreur.
Et d'où le commentaire que vous ne devez pas modifier le paramètre de classment (ce qui permettrait d'adresses de messagerie invalides).

Comme indiqué, ToUpper (qui devrait être ToUpperInvariant) est à blâmer, parce que dans les coulisses change le 'i' en 'İ', qui n'est pas un caractère ASCII valide.

C'est un problème courant avec la méthode ToUpper d'une string / caractère.
Par exemple, l'alphabet allemand contient la lettre ß (Unicode U + 00DF), également appelée "double s", qui n'a pas de caractère majuscule correspondant, donc si vous essayez de comparer des strings avec toUpper, il échouera toujours, C'est pourquoi vous devriez toujours utiliser ToLower () pour comparer les strings – un autre Microsoft échoue.

Une chose similaire arrive ici avec ToUpper.

Ce que vous devez faire en premier lieu est de s'assurer que vos users entrent des caractères ASCII.
Ce n'est pas possible car ils ont un keyboard turc et une locale, et tandis que le petit i ressemblera au petit i d'ASCII, il a une représentation numérique différente, et donc une majuscule différente (et des minuscules aussi bien que btw).

Donc, ce que vous devez faire est de "latiniser / romaniser" votre string d'input, avant d'appeler la méthode d'adhésion.

J'ai rencontré des problèmes similaires avec des logiciels compatibles ASCII d'un tiers, qui ont échoué sur les trémas et les caractères d'accent français, et j'ai utilisé la méthode ci-dessous pour résoudre ce problème.
Vous voudrez peut-être vérifier si le äöü turc n'a pas une représentation numérique différente du äöü (suisse) allemand que j'ai utilisé ici.

Pour les risques et les effets secondaires, lisez les notices et requestz à votre médecin ou à votre pharmacien.

  // ssortingng str = ApertureSucks.Latinize("(æøå âôû?aè"); public static ssortingng Latinize(ssortingng stIn) { // Special treatment for German Umlauts stIn = stIn.Replace("ä", "ae"); stIn = stIn.Replace("ö", "oe"); stIn = stIn.Replace("ü", "ue"); stIn = stIn.Replace("Ä", "Ae"); stIn = stIn.Replace("Ö", "Oe"); stIn = stIn.Replace("Ü", "Ue"); // End special treatment for German Umlauts ssortingng stFormD = stIn.Normalize(System.Text.NormalizationForm.FormD); System.Text.SsortingngBuilder sb = new System.Text.SsortingngBuilder(); for (int ich = 0; ich < stFormD.Length; ich++) { System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); if (uc != System.Globalization.UnicodeCategory.NonSpacingMark) { sb.Append(stFormD[ich]); } // End if (uc != System.Globalization.UnicodeCategory.NonSpacingMark) } // Next ich //return (sb.ToSsortingng().Normalize(System.Text.NormalizationForm.FormC)); return (sb.ToSsortingng().Normalize(System.Text.NormalizationForm.FormKC)); } // End Function Latinize 

Et last but not least, je n'utiliserais pas le fournisseur d'appartenance ASP.NET embedded, car il joint les tables via nom d'user + nom d'application à rolename, au lieu d'utiliser un identifiant unique. Cela signifie que vous ne pourrez pas modifier un nom d'user ou de groupe / rôle sans modifier toutes les tables de mappage. Je pense que faire cela de cette façon est hautement indésirable, et certainement stupide et négligent, sinon carrément dangereux de la part de Microsoft.
J'irais même jusqu'à dire qu'il est impudent de libérer de telles ordures dans la nature.

La "chose" ci-dessous démontre la stupidité totale du problème et ne devrait jamais être utilisée

 CREATE TABLE [dbo].[UsersInRoles]( [Username] [varchar](255) NOT NULL, [Rolename] [varchar](255) NOT NULL, [ApplicationName] [varchar](255) NOT NULL, CONSTRAINT [usersinroles_pkey] PRIMARY KEY CLUSTERED ( [Username] ASC, [Rolename] ASC, [ApplicationName] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] 

Pour les raisons suivantes:

  • Problème 1: la jointure de string rendra l'user au rôle très lent – très mauvais pour la performance
  • Problème 2: varchar – devrait être nvarchar, sauf si vous vivez dans un univers en anglais seulement
  • Problème 3: la longueur du nom d'user et du nom de domaine doit être conforme aux spécifications minimales du dernier active directory, sinon il y aura des problèmes de synchronisation avec le directory activé. Plus Active Directory permet les caractères Unicode.
  • Problème 4: Aucune reference de key étrangère à la table des users et des rôles – finit tôt ou tard avec la poubelle de données (généralement plus tôt)
  • Problème 5: si maintenant vous changez le nom d'user ou le nom de groupe, UserInRoles ne sera pas mis à jour et le mappage de groupe des users sera orphelin – finit avec des données corrompues, les jointures à gauche apporteront des colonnes vides, les programmes pourraient planter à cause de NullReferenceException non gérée.
  • Problème 6: parce que la reference de key étrangère est manquante, il est possible de changer un nom d'user / nom de groupe
  • Problème 7: la faille de données mènera tôt ou tard à plusieurs lignes lors de la création de rapports / affichage de données
  • Problème 8: La key primaire utilisée ici devrait plutôt être une contrainte unique
  • Problème 9: Il y a UN nom de groupe, mais par exemple, le groupe «administrateurs» doit être localisé dans plusieurs langues, ce que le fournisseur d'appartenances ne prend pas en charge. De plus, le nom de groupe appartient à une table de mappage, car un groupe peut avoir N noms pour N langues, puis il faut s'assurer que le nom de groupe est unique dans une langue spécifique.
  • Problème 10: Non visible ici, mais la table user contient un champ e-mail. C'est un échec total car un user peut avoir n adresses email, et un fournisseur d'adhésion intelligent devrait en tenir count, au lieu de limiter bêtement l'user à une seule adresse e-mail.
  • Problème 11: De plus, le champ e-mail mentionné est limité à 128 caractères, ce qui est inférieur au nombre maximum autorisé de caractères autorisés dans une adresse e-mail selon la RFC. FAIL – tôt ou tard quelqu'un sera incapable de saisir son adresse mail – même s'il n'en a qu'une. Quelle est la longueur maximale d'une adresse e-mail valide?

et je suis sûr qu'il y a beaucoup plus de problèmes avec le fiasco de fournisseur d'adhésion fourni par MS. Par exemple en utilisant un algorithm de hachage rapide (MD5), qui est un anti-model pour ce cas, car cela permet une attaque de table arc-en-ciel, surtout si le hachage n'est pas salé. Si le fournisseur d'appartenances MS montre une chose, alors voici comment ne pas concevoir un fournisseur d'appartenances.

Oui, la solution consiste à utiliser ToUpperInvariant () lorsque vous créez l'user et le count WebSecurity.CreateUserAndAccount (model.UserName.ToUpperInvariant ()); . Cela résoudra le problème. Les valeurs seront stockées dans la table avec une majuscule ([email protected]).