Как перенести пользователей Identity из приложения MVC5 в приложение ASP.NET Core 2.2 - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть веб-приложение, построенное на MVC5 с использованием Identity.Я хочу преобразовать этот проект в веб-приложение ASP.NET Core 2.2.Я создал новое веб-приложение ASP.NET Core 2.2 с аутентификацией, настроенной на Индивидуальные учетные записи пользователей, и добавил свою базу данных в проект, следуя этим инструкциям .Затем я добавил новый элемент Identity Scaffolded в свой проект, добавил миграцию и обновил базу данных.

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

Я хотел бы сохранить свою старую базу данных, но преобразовать ее, чтобы использовать новые страницы Identity Razor, встроенные в ASP.NET Core.Каков наилучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 17 июля 2019

После обновления таблиц идентификации вы можете обновить существующих пользователей хэши паролей.Некоторые новые столбцы в таблице AspNetUsers будут иметь значения NULL.Сначала запустите это:

UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(Email)
WHERE NormalizedEmail IS NULL

NormalizedUserName фактически обновлено в верхнем регистре email .

Нам нужен способ, чтобы отличить пользователейиспользовать новую версию хэша или нет.

Один из способов - добавить новое свойство в IdentityUser:

public class ApplicationUser : IdentityUser
{
    public PasswordHashVersion HashVersion { get; set; }

    public ApplicationUser()
    {
        this.HashVersion = PasswordHashVersion.Core;
    }
}

public enum PasswordHashVersion
{
    OldMvc,
    Core
}

Для существующих пользователей будет задано значение по умолчанию PasswordHashVersion равно нулю (OldMvc), новые зарегистрированныепользователи будут по умолчанию один (основной).Если у вас есть более умный способ определить, является ли хэш новым или старым алгоритмом, вам это не нужно.

Затем мы создадим пользовательский PasswordHash, который использует реализацию старого алгоритма хеширования по умолчанию :

public class OldMvcPasswordHasher : PasswordHasher<ApplicationUser>
{
    public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
    {
        // if it's the new algorithm version, delegate the call to parent class
        if (user.HashVersion == PasswordHashVersion.Core)
            return base.VerifyHashedPassword(user, hashedPassword, providedPassword);

        byte[] buffer4;
        if (hashedPassword == null)
        {
            return PasswordVerificationResult.Failed;
        }
        if (providedPassword == null)
        {
            throw new ArgumentNullException("providedPassword");
        }
        byte[] src = Convert.FromBase64String(hashedPassword);
        if ((src.Length != 0x31) || (src[0] != 0))
        {
            return PasswordVerificationResult.Failed;
        }
        byte[] dst = new byte[0x10];
        Buffer.BlockCopy(src, 1, dst, 0, 0x10);
        byte[] buffer3 = new byte[0x20];
        Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
        using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(providedPassword, dst, 0x3e8))
        {
            buffer4 = bytes.GetBytes(0x20);
        }
        if (AreHashesEqual(buffer3, buffer4))
        {
            user.HashVersion = PasswordHashVersion.Core;
            return PasswordVerificationResult.SuccessRehashNeeded;
        }
        return PasswordVerificationResult.Failed;
    }

    private bool AreHashesEqual(byte[] firstHash, byte[] secondHash)
    {
        int _minHashLength = firstHash.Length <= secondHash.Length ? firstHash.Length : secondHash.Length;
        var xor = firstHash.Length ^ secondHash.Length;
        for (int i = 0; i < _minHashLength; i++)
            xor |= firstHash[i] ^ secondHash[i];
        return 0 == xor;
    }
}

Этот класс наследует новое Identity Core PasswordHasher.Если версия хэша пароля пользователя уже использует новый алгоритм (например, HashVersion = Core), то мы просто вызываем базовый метод из PasswordHasher, который использует новый алгоритм.В противном случае используйте старый алгоритм идентификации для проверки пароля.

Если пароль совпадает, мы обновляем версию хэша пароля пользователя до Core и возвращаем PasswordVerificationResult.SuccessRehashNeeded, чтобы принудительно обновить существующий хэш с помощью нового алгоритма..

Наконец, вам нужно убедиться, что ваш пользовательский PasswordHasher используется.Добавьте это к Startup.cs внутри ConfigureServices:

// Replace the existing scoped IPasswordHasher<> implementation
services.Replace(new ServiceDescriptor(
    serviceType: typeof(IPasswordHasher<ApplicationUser>),
    implementationType: typeof(OldMvcPasswordHasher),
    ServiceLifetime.Scoped));

Это необходимо добавить после любых вызовов на AddIdentity, AddDefaultIdentity или AddIdentityCore.

Это будет медленно обновлять хэши паролей по мере аутентификации ваших пользователей.

0 голосов
/ 24 июля 2019

Альтернативным решением будет экспорт / импорт данных в новые таблицы.Это то, что я сделал по нескольким причинам, но, в конечном счете, я не хотел изменять исходную таблицу на тот случай, если она понадобится мне быстро и безболезненно.

Короче говоря, вы можете выполнять прямой импорт / экспорт ваших старых данных в новые таблицы идентификаторов, и единственное, что НУЖНО, это нормализованные значения имени пользователя и адреса электронной почты.

Было бы замечательно, если бы Identity могла обрабатывать это внутренне, поскольку обрабатывает (обновляет) новый хэш пароля, метку безопасности и метку параллелизма без проблем при первом входе пользователя в систему.

Очень быстрый и простой способ переноса пользователей с неповрежденными паролями:

1) Экспорт таблицы пользователей из старой версии Identity в файл CSV.

2) Откройте этот CSV-файл в Excel и добавьте в CSV-файл три столбца для двух отсутствующих столбцов нормализации (имя пользователя и адрес электронной почты) и один отсутствующий столбец отметки параллелизма (столбец параллелизма на самом деле не является)необходимо).

3) В первом пустом столбце нормализации (обычно c2) добавьте формулу Excel =UPPER(b2) (где b2 - это поле, в котором вы видите первое значениепытаясь нормализовать ... например, Username = b2 или Email = d2 при прямом экспорте, где вы помещаете нормализованные столбцы рядом с их ненормализованными аналогами).Нажмите ввод, и вы должны увидеть значение верхнего регистра в поле сейчас.

4) Перетащите эту формулу до конца электронной таблицы, нормализуя все имена пользователей и электронные письма к их значениям в верхнем регистре (т.е. все в верхнем регистре = нормализованные).

5) Скопируйте значения в верхнем регистре из электронной таблицы и вставьте их в пустой файл блокнота ... затем скопируйте их обратно в электронную таблицу в том же месте (которое переписывает формулы с нормализованными значениями. Excel может бытьдостаточно умен, чтобы избавиться от формул и сохранить нормализованные значения при сохранении в формате CSV, но я его не проверял).

6) Сохраните электронную таблицу обратно в виде CSV и импортируйте еек новой таблице идентификации AspnetUsers.

Штамп параллелизма можно оставить пустым, а последняя личность позаботится обо всем остальном, как только пользователь войдет в систему в первый раз.

Идентификация такжене входите в систему с именами пользователей, если вы не включили это в новой версии и не сделали это в старой версии (так что вам нужно либо включить эту функцию, либо преобразовать yoВаши имена пользователей на их соответствующие адреса электронной почты, прежде чем вы сможете успешно войти в систему).

Это не красиво, но для разовой работы мне понадобилось менее 15 минут, чтобы перенести пользователей из Identity 4.0.30319 в Core 2.2.с помощью этого метода и никаких изменений пароля не требуется.Мне потребовалось больше времени, чтобы напечатать все это, чем перенести моих пользователей.Надеюсь, это поможет.

0 голосов
/ 12 января 2019

В то время как документация Microsoft была несколько полезной.Самая полезная информация была в комментариях.

Мне удалось перенести существующие БД, выполнив следующие действия:

  • Создайте новый проект ASP.net Core и измените его ModelSnapshot на
    в соответствии с EF6.После этого вы можете сгенерировать скрипт для изменений EF6 в EF Core.

  • Написать скрипт для обновления таблицы AspNetUsers.В ядре ASP.net
    для идентификации при аутентификации используется NormalizedEmail,
    NormalizedUserName столбцы.Поэтому нам нужно обновить эти два столбца
    , используя наши существующие данные.

Вот ссылка на GitHub для скриптов для обновления таблиц. Migration.zip

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...