Адрес электронной почты как имя пользователя BUG - программирование
Подтвердить что ты не робот

Адрес электронной почты как имя пользователя BUG

Я разрабатываю веб-сайт MVC4 с базой данных SQL Server. Я хочу зарегистрировать людей с их адресом электронной почты.

Однако если адрес электронной почты содержит символ i, метод WebSecurity.CreateUserAndAccount генерирует исключение, говорит:

Поставщик проверки подлинности вернул ошибку. Проверьте свою и повторите попытку. Если проблема не устранена, обратитесь к своему системного администратора.

Я много исследовал и нашел несколько сообщений об этом, но решения нет.

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

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

4b9b3361

Ответ 1

Ваша основная проблема заключается в том, что вы пытаетесь ввести символы не ASCII в качестве адреса электронной почты.

"Набор символов ASCII" ограничивает вас американско-английским алфавитом, который является латинским алфавитом.

Я не говорю по-турецки, но как указано в http://aspnetwebstack.codeplex.com/workitem/714

На турецком языке "i" имеет строчные буквы, а "İ" - верхняя часть "i".
В латинском алфавите, который у вас (и меня) не имеет IT-мудрый, "i" имеет строчный регистр, а "I" - в верхнем регистре i.

Итак, у вас есть персонаж, который не является членом набора символов EN-US ASCII.
Таким образом, настройка сортировки не позволяет вводить символы не ASCII в вашу базу данных, следовательно, ошибка.
И, следовательно, комментарий, что вы НЕ измените настройку сопоставления (что позволило бы недействительные почтовые адреса).

Как указано, ToUpper (который должен быть ToUpperInvariant) виноват, потому что он за кулисами меняет "i" на "İ", что не является допустимым символом ASCII.

Это обычная проблема с методом ToUpper строки/символа.
Например, немецкий алфавит содержит букву ß (Unicode U + 00DF), также известную как "double s", которая не имеет соответствующего символа верхнего регистра в первую очередь, поэтому, если вы попытаетесь сравнить строки, используя toUpper, она всегда будет терпеть неудачу, поэтому вы всегда должны использовать ToLower() для сравнения строк - другая ошибка Microsoft.

Аналогичная ситуация происходит с ToUpper.

Что вам нужно сделать в первую очередь - это обеспечить, чтобы ваши пользователи вводили символы ASCII.
Это невозможно, поскольку у них есть турецкая клавиатура и локаль, а в то время как маленький я буду похож на маленький ASCII i, он имеет другое числовое представление и, следовательно, другой символ верхнего регистра (и строчный, а также btw).

Итак, вам нужно сделать так, чтобы "latinize/romanize" ваша строка ввода, до вызова метода членства.

У меня были аналогичные проблемы с совместимым с ASCII программным обеспечением от третьей стороны, которая не удалась на умляутах и ​​французских символах акцента, и использовал приведенный ниже метод для решения этой проблемы.

Возможно, вам захочется проверить, нет ли у турецкого äöü другого численного представления, чем (швейцарский) немецкий äöü, который я использовал здесь.

Для рисков и побочных эффектов прочитайте листовки и спросите своего врача или фармацевта.

    // string str = ApertureSucks.Latinize("(æøå âôû?aè");
    public static string Latinize(string 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

        string stFormD = stIn.Normalize(System.Text.NormalizationForm.FormD);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();

        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.ToString().Normalize(System.Text.NormalizationForm.FormC));
        return (sb.ToString().Normalize(System.Text.NormalizationForm.FormKC));
    } // End Function Latinize

И последнее, но не менее важное: я бы не использовал встроенный провайдер членства ASP.NET, потому что он объединяет таблицы через имя пользователя + имя приложения в rollename, вместо использования уникального идентификатора. Это означает, что вы не сможете изменить имя пользователя или группы/роли без изменения всех таблиц сопоставления. Я думаю, что делать это так крайне нежелательно и, безусловно, глупо и небрежно, если не совсем опасно для Microsoft.

Я бы дошел до того, чтобы называть его бессовестным, чтобы выпустить такой мусор в дикую природу.

Нижеследующая "вещь" демонстрирует проблему полной глупости и никогда не должна использоваться

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]

по следующим причинам:

  • Проблема 1: объединение строк приведет к тому, что пользователь будет играть роль очень медленно - очень плохо для производительности
  • Проблема 2: varchar - должен быть nvarchar, если только вы живете в единственной англоязычной вселенной.
  • Задача 3: длина поля имя пользователя и ролевое имя должны соответствовать минимальным спецификациям последних активных в противном случае будут проблемы с синхронизацией с ActiveDirectory. Plus Active позволяет использовать символы Unicode.
  • Проблема 4: Нет ссылки на внешний ключ для таблицы пользователей и ролей - заканчивается с мусором данных рано или поздно (обычно раньше)
  • Проблема 5: если теперь вы меняете имя пользователя или groupname, UserInRoles не будет обновляться, а группа пользователей отображение будет сиротой - заканчивается мусором данных, левые соединения будут приносить пустые столбцы, программы могут вылетать из-за необработанного исключения NullReferenceException.
  • Проблема 6: поскольку ссылка на внешний ключ отсутствует, можно изменить имя пользователя /groupname
  • Проблема 7: мусор данных рано или поздно приведет к многократным строкам при представлении/отображении данных
  • Проблема 8: Первичный ключ, используемый здесь, должен быть уникальным ограничением
  • Проблема 9: Существует одно имя группы, но, например, группа "администраторы" должна быть локализована на многих языках, которые поставщик членства не поддерживает. Кроме того, имя группы принадлежит таблице сопоставления, поскольку одна группа может иметь N имен для N языков, а затем необходимо обеспечить, чтобы имя группы было уникальным на определенном языке.
  • Проблема 10: здесь не видно, но таблица пользователя содержит полевое электронное письмо. Это полный сбой, потому что один пользователь может иметь n адресов электронной почты, а интеллектуальный членский провайдер должен учитывать это, вместо того, чтобы глупо ограничивать пользователя одним адресом электронной почты.
  • Проблема 11: Кроме того, указанное поле электронной почты ограничено 128 символами, что меньше максимально допустимого количества символов, разрешенных на адрес электронной почты в соответствии с rfc. FAIL - рано или поздно кто-то не сможет ввести свой почтовый адрес, даже если у него есть только один. Какова максимальная длина действительного адреса электронной почты?

и я уверен, что существует много проблем с фиаско-членством в поставщике-поставщике. Например, используя алгоритм быстрого хэша (MD5), который является антипаттерном для этого случая, поскольку это позволяет атаковать радужным столом, особенно если хэш не солен. Если поставщик членства в MS демонстрирует одну вещь, то именно так НЕ следует создавать поставщика членства.

Ответ 2

Да, решение заключается в использовании ToUpperInvariant() при создании пользователя и учетной записи WebSecurity.CreateUserAndAccount(model.UserName.ToUpperInvariant()); , Это решит проблему. Значения будут сохранены в таблице с прописной буквой ([email protected]).