Migrowanie istniejącej witryny internetowej z członkostwa SQL do systemu ASP.NET Identity

Autor Rick Anderson, Suhas Joshi

W tym samouczku przedstawiono procedurę migrowania istniejącej aplikacji sieci Web z danymi użytkownika i roli utworzonych przy użyciu członkostwa SQL w nowym systemie ASP.NET Identity. To podejście obejmuje zmianę istniejącego schematu bazy danych na ten, który jest wymagany przez ASP.NET Identity i hak w stare/nowe klasy do niego. Po zastosowaniu tej metody po migracji bazy danych przyszłe aktualizacje tożsamości będą obsługiwane bezproblemowo.

W tym samouczku utworzymy szablon aplikacji sieci Web (Formularze sieci Web) utworzony za pomocą programu Visual Studio 2010 do tworzenia danych użytkownika i roli. Następnie użyjemy skryptów SQL do przeprowadzenia migracji istniejącej bazy danych do tabel wymaganych przez system tożsamości. Następnie zainstalujemy wymagane pakiety NuGet i dodamy nowe strony zarządzania kontami, które używają systemu tożsamości do zarządzania członkostwem. W ramach testu migracji użytkownicy utworzeni przy użyciu członkostwa SQL powinni mieć możliwość zalogowania się, a nowi użytkownicy powinni mieć możliwość zarejestrowania się. Pełny przykład można znaleźć tutaj. Zobacz również Migrowanie z członkostwa ASP.NET do ASP.NET Identity.

Wprowadzenie

Tworzenie aplikacji z członkostwem SQL

  1. Musimy zacząć od istniejącej aplikacji, która korzysta z członkostwa SQL i ma dane dotyczące użytkowników i ról. Na potrzeby tego artykułu utworzymy aplikację sieci Web w programie Visual Studio 2010.

  2. Za pomocą narzędzia do konfiguracji ASP.NET utwórz 2 użytkowników: oldAdminUser i oldUser.

  3. Utwórz rolę o nazwie admin i Dodaj "oldAdminUser" jako użytkownika w tej roli.

  4. Utwórz sekcję administratora witryny z wartością default. aspx. Ustaw tag autoryzacja w pliku web.config, aby umożliwić dostęp tylko użytkownikom w rolach administratora. Więcej informacji można znaleźć tutaj https://www.asp.net/web-forms/tutorials/security/roles/role-based-authorization-cs

  5. Wyświetl bazę danych w Eksplorator serwera, aby zrozumieć tabele utworzone przez system członkostwa SQL. Dane logowania użytkownika są przechowywane w _ tabelach użytkownicy ASPNET i ASPNET _ Membership, podczas gdy dane roli są przechowywane w _ tabeli role ASPNET. Informacje o użytkownikach, w których role są przechowywane w _ tabeli UsersInRoles ASPNET. Aby zarządzać członkostwem w warstwie Podstawowa, wystarczy przenieść informacje w powyższych tabelach do systemu ASP.NET Identity.

Migrowanie do Visual Studio 2013

  1. Zainstaluj Visual Studio Express 2013 dla sieci Web lub Visual Studio 2013 wraz z najnowszymi aktualizacjami.

  2. Otwórz powyższy projekt w zainstalowanej wersji programu Visual Studio. Jeśli na komputerze nie zainstalowano SQL Server Express, podczas otwierania projektu zostanie wyświetlony monit, ponieważ parametry połączenia korzystają z programu SQL Express. Możesz wybrać opcję instalacji programu SQL Express lub obejść, aby zmienić parametry połączenia na LocalDb. W tym artykule zmienimy ją na LocalDb.

  3. Otwórz web.config i Zmień parametry połączenia z. SQLExpress do (LocalDb) v 11.0. Usuń "wystąpienie użytkownika = true" z parametrów połączenia.

  4. Otwórz Eksplorator serwera i sprawdź, czy można zaobserwować schemat i dane tabeli.

  5. System ASP.NET Identity działa w wersji 4,5 lub nowszej. Przekieruj aplikację do wersji 4,5 lub nowszej.

    Skompiluj projekt, aby sprawdzić, czy nie wystąpiły żadne błędy.

Instalowanie pakietów NuGet

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt > Zarządzanie pakietami NuGet. W polu wyszukiwania wprowadź ciąg "Asp.net Identity" (tożsamość tożsamości). Wybierz pakiet z listy wyników, a następnie kliknij przycisk Instaluj. Zaakceptuj umowę licencyjną, klikając przycisk "Akceptuję". Należy pamiętać, że ten pakiet zainstaluje pakiety zależności: EntityFramework i Microsoft ASP.NET Identity Core. Podobnie Zainstaluj następujące pakiety (Pomiń ostatnie 4 pakiety OWIN, jeśli nie chcesz włączyć logowania OAuth):

    • Microsoft. AspNet. Identity. Owin

    • Microsoft.Owin.Host.SystemWeb

    • Microsoft. Owin. Security. Facebook

    • Microsoft. Owin. Security. Google

    • Microsoft. Owin. Security. MicrosoftAccount

    • Microsoft. Owin. Security. Twitter

Migrowanie bazy danych do nowego systemu tożsamości

Następnym krokiem jest przeprowadzenie migracji istniejącej bazy danych do schematu wymaganego przez system ASP.NET Identity. Aby to osiągnąć, należy uruchomić skrypt SQL, który zawiera zestaw poleceń umożliwiających tworzenie nowych tabel i Migrowanie istniejących informacji o użytkowniku do nowych tabel. Plik skryptu można znaleźć tutaj.

Ten plik skryptu jest specyficzny dla tego przykładu. Jeśli schemat tabel utworzonych przy użyciu członkostwa SQL jest dostosowywany lub modyfikowany, należy odpowiednio zmienić skrypty.

Jak wygenerować skrypt SQL na potrzeby migracji schematu

Aby ASP.NET Identity klasy do pracy z danymi istniejących użytkowników, musimy zmigrować schemat bazy danych do tego, co jest wymagane przez ASP.NET Identity. Możemy to zrobić przez dodanie nowych tabel i skopiowanie istniejących informacji do tych tabel. Domyślnie ASP.NET Identity używa EntityFramework do mapowania klas modelu tożsamości z powrotem do bazy danych w celu przechowywania/pobierania informacji. Te klasy modelu implementują podstawowe interfejsy tożsamości definiujące obiekty użytkowników i ról. Tabele i kolumny w bazie danych są oparte na tych klasach modelu. Klasy modelu EntityFramework w 2.1.0 Identity v i ich właściwości są zgodne z definicją poniżej

IdentityUser Typ IdentityRole IdentityUserRole IdentityUserLogin IdentityUserClaim
Id ciąg Id RoleId ProviderKey Id
Nazwa użytkownika ciąg Nazwa UserId UserId Claim
PasswordHash ciąg LoginProvider ClaimValue
SecurityStamp ciąg _Identyfikator użytkownika
E-mail ciąg
EmailConfirmed bool
PhoneNumber ciąg
PhoneNumberConfirmed bool
LockoutEnabled bool
LockoutEndDate DateTime
AccessFailedCount int

Musimy mieć tabele dla każdego z tych modeli z kolumnami odpowiadającymi właściwościom. Mapowanie między klasami i tabelami jest zdefiniowane w OnModelCreating metodzie IdentityDBContext . Jest to tzw. Metoda konfiguracji interfejsu API Fluent i więcej informacji można znaleźć tutaj. Konfiguracja klas została opisana poniżej

Klasa Tabela Klucz podstawowy Klucz obcy
IdentityUser AspnetUsers Id
IdentityRole AspnetRoles Id
IdentityUserRole AspnetUserRole Identyfikator użytkownika i RoleId _Identyfikator użytkownika- > AspnetUsers RoleId- > AspnetRoles
IdentityUserLogin AspnetUserLogins ProviderKey + UserId + LoginProvider UserId — > AspnetUsers
IdentityUserClaim AspnetUserClaims Id _Identyfikator użytkownika — > AspnetUsers

Za pomocą tych informacji możemy utworzyć instrukcje SQL, aby utworzyć nowe tabele. Możemy ręcznie napisać każdą instrukcję lub wygenerować cały skrypt za pomocą poleceń programu PowerShell EntityFramework, które możemy edytować zgodnie z potrzebami. W tym celu w programie VS Otwórz konsolę Menedżera pakietów z menu Widok lub Narzędzia .

  • Uruchom polecenie "Enable-migrations", aby włączyć migracje EntityFramework.
  • Uruchom polecenie "Add-Migration Initial", które tworzy początkowy kod instalatora w celu utworzenia bazy danych w języku C#/VB.
  • Ostatnim krokiem jest uruchomienie polecenia "Update-Database-Script", które generuje skrypt SQL na podstawie klas modelu.

Niektóre polecenia nie są obsługiwane, jeśli aplikacja używa oprogramowania SQLite jako magazynu danych tożsamości. Ze względu na ograniczenia w aparacie bazy danych polecenia Alter zgłaszają następujący wyjątek:

"System. NotSupportedException: Program SQLite nie obsługuje tej operacji migracji".

Aby to obejść, uruchom Code First migracji w bazie danych, aby zmienić tabele.

Ten skrypt generowania bazy danych może służyć jako początek, w którym będziemy wprowadzać dodatkowe zmiany w celu dodawania nowych kolumn i kopiowania danych. Zaletą tego jest generowanie _MigrationHistory tabeli, która jest używana przez EntityFramework do modyfikowania schematu bazy danych, gdy klasy modelu zmieniają się w przyszłych wersjach tożsamości.

Informacje o użytkowniku członkostwa w programie SQL mają inne właściwości oprócz tych, które są używane w klasie modelu użytkownika tożsamości, w tym adres e-mail, próby hasła, Data ostatniego logowania, Data ostatniego zablokowania itd. Jest to przydatne informacje, które chcemy przenieść do systemu tożsamości. Można to zrobić, dodając dodatkowe właściwości do modelu użytkownika i mapując je z powrotem do kolumn tabeli w bazie danych. Możemy to zrobić przez dodanie klasy, która jest podklasą IdentityUser modelu. Można dodać właściwości do tej klasy niestandardowej i edytować skrypt SQL, aby dodać odpowiednie kolumny podczas tworzenia tabeli. Kod dla tej klasy został szczegółowo opisany w artykule. Skrypt SQL służący do tworzenia AspnetUsers tabeli po dodaniu nowych właściwości zostałby

CREATE TABLE [dbo].[AspNetUsers] (
    [Id]            NVARCHAR (128) NOT NULL,
    [UserName]      NVARCHAR (MAX) NULL,
    [PasswordHash]  NVARCHAR (MAX) NULL,
    [SecurityStamp] NVARCHAR (MAX) NULL,
    [EmailConfirmed]       BIT            NOT NULL,
    [PhoneNumber]          NVARCHAR (MAX) NULL,
    [PhoneNumberConfirmed] BIT            NOT NULL,
    [TwoFactorEnabled]     BIT            NOT NULL,
    [LockoutEndDateUtc]    DATETIME       NULL,
    [LockoutEnabled]       BIT            NOT NULL,
    [AccessFailedCount]    INT            NOT NULL,
    [ApplicationId]                          UNIQUEIDENTIFIER NOT NULL,
    [LegacyPasswordHash]  NVARCHAR (MAX) NULL,
    [LoweredUserName]  NVARCHAR (256)   NOT NULL,
    [MobileAlias]      NVARCHAR (16)    DEFAULT (NULL) NULL,
    [IsAnonymous]      BIT              DEFAULT ((0)) NOT NULL,
    [LastActivityDate] DATETIME2         NOT NULL,
    [MobilePIN]                              NVARCHAR (16)    NULL,
    [Email]                                  NVARCHAR (256)   NULL,
    [LoweredEmail]                           NVARCHAR (256)   NULL,
    [PasswordQuestion]                       NVARCHAR (256)   NULL,
    [PasswordAnswer]                         NVARCHAR (128)   NULL,
    [IsApproved]                             BIT              NOT NULL,
    [IsLockedOut]                            BIT              NOT NULL,
    [CreateDate]                             DATETIME2               NOT NULL,
    [LastLoginDate]                          DATETIME2         NOT NULL,
    [LastPasswordChangedDate]                DATETIME2         NOT NULL,
    [LastLockoutDate]                        DATETIME2         NOT NULL,
    [FailedPasswordAttemptCount]             INT              NOT NULL,
    [FailedPasswordAttemptWindowStart]       DATETIME2         NOT NULL,
    [FailedPasswordAnswerAttemptCount]       INT              NOT NULL,
    [FailedPasswordAnswerAttemptWindowStart] DATETIME2         NOT NULL,
    [Comment]                                NTEXT            NULL,
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC),
    FOREIGN KEY ([ApplicationId]) REFERENCES [dbo].[aspnet_Applications] ([ApplicationId]),
);

Następnie musimy skopiować istniejące informacje z bazy danych członkostwa SQL do nowo dodanych tabel dla tożsamości. Można to zrobić za pomocą języka SQL, kopiując dane bezpośrednio z jednej tabeli do drugiej. Aby dodać dane do wierszy tabeli, używamy INSERT INTO [Table] konstrukcji. Aby skopiować z innej tabeli, możemy użyć INSERT INTO instrukcji wraz z SELECT instrukcją. Aby uzyskać wszystkie informacje o użytkowniku, musimy wysłać zapytanie do tabel " _ Użytkownicy ASPNET " i " _ członkostwo ASPNET " i skopiować dane do tabeli AspNetUsers . Używamy INSERT INTO instrukcji i SELECT wraz z JOIN LEFT OUTER JOIN instrukcjami. Aby uzyskać więcej informacji na temat wykonywania zapytań i kopiowania danych między tabelami, Skorzystaj z tego linku. Ponadto tabele AspnetUserLogins i AspnetUserClaims są puste, aby zacząć od, ponieważ nie ma żadnych informacji w członkostwie SQL, które są domyślnie mapowane na ten program. Jedyne skopiowane informacje dotyczą użytkowników i ról. W przypadku projektu utworzonego w poprzednich krokach zapytanie SQL do kopiowania informacji do tabeli użytkownicy byłyby

INSERT INTO AspNetUsers(Id,UserName,PasswordHash,SecurityStamp,EmailConfirmed,
PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,
ApplicationId,LoweredUserName,MobileAlias,IsAnonymous,LastActivityDate,LegacyPasswordHash,
MobilePIN,Email,LoweredEmail,PasswordQuestion,PasswordAnswer,IsApproved,IsLockedOut,CreateDate,
LastLoginDate,LastPasswordChangedDate,LastLockoutDate,FailedPasswordAttemptCount,
FailedPasswordAnswerAttemptWindowStart,FailedPasswordAnswerAttemptCount,FailedPasswordAttemptWindowStart,Comment)
SELECT aspnet_Users.UserId,aspnet_Users.UserName,(aspnet_Membership.Password+'|'+CAST(aspnet_Membership.PasswordFormat as varchar)+'|'+aspnet_Membership.PasswordSalt),NewID(),
'true',NULL,'false','true',aspnet_Membership.LastLockoutDate,'true','0',
aspnet_Users.ApplicationId,aspnet_Users.LoweredUserName,
aspnet_Users.MobileAlias,aspnet_Users.IsAnonymous,aspnet_Users.LastActivityDate,aspnet_Membership.Password,
aspnet_Membership.MobilePIN,aspnet_Membership.Email,aspnet_Membership.LoweredEmail,aspnet_Membership.PasswordQuestion,aspnet_Membership.PasswordAnswer,
aspnet_Membership.IsApproved,aspnet_Membership.IsLockedOut,aspnet_Membership.CreateDate,aspnet_Membership.LastLoginDate,aspnet_Membership.LastPasswordChangedDate,
aspnet_Membership.LastLockoutDate,aspnet_Membership.FailedPasswordAttemptCount, aspnet_Membership.FailedPasswordAnswerAttemptWindowStart,
aspnet_Membership.FailedPasswordAnswerAttemptCount,aspnet_Membership.FailedPasswordAttemptWindowStart,aspnet_Membership.Comment
FROM aspnet_Users
LEFT OUTER JOIN aspnet_Membership ON aspnet_Membership.ApplicationId = aspnet_Users.ApplicationId 
AND aspnet_Users.UserId = aspnet_Membership.UserId;

W powyższej instrukcji języka SQL informacje o każdym użytkowniku z tabel _ Użytkownicy ASPNET i ASPNET _ Membership są kopiowane do kolumn tabeli AspnetUsers . Jedyną modyfikacją wykonywaną w tym miejscu jest skopiowanie hasła. Ponieważ algorytm szyfrowania dla haseł w członkostwie w programie SQL Server użył "PasswordSalt" i "PasswordFormat", jest on kopiowany również przy użyciu hasła skrótu, aby można było go użyć do odszyfrowania hasła przez tożsamość. Jest to wyjaśnione dalej w artykule podczas podłączania niestandardowego skrótu hasła.

Ten plik skryptu jest specyficzny dla tego przykładu. W przypadku aplikacji, które mają dodatkowe tabele, deweloperzy mogą postępować zgodnie z podobnym podejściem do dodawania dodatkowych właściwości klasy modelu użytkownika i mapowania ich do kolumn w tabeli AspnetUsers. Aby uruchomić skrypt,

  1. Otwórz Eksplorator serwera. Rozwiń połączenie "ApplicationServices", aby wyświetlić tabele. Kliknij prawym przyciskiem myszy węzeł tabele i wybierz opcję "nowe zapytanie"

  2. W oknie zapytania skopiuj i wklej cały skrypt SQL z pliku migrations. SQL. Uruchom plik skryptu, naciskając przycisk strzałki "wykonaj".

    Odśwież okno Eksplorator serwera. W bazie danych są tworzone pięć nowych tabel.

    Poniżej przedstawiono sposób mapowania informacji w tabelach członkostwa SQL do nowego systemu tożsamości.

    _role ASPNET — > AspNetRoles

    _Użytkownicy _ firmowi ASP i webmemberer — > AspNetUsers

    ASPNET _ UserInRoles-- > AspNetUserRoles

    Zgodnie z opisem w powyższej sekcji tabele AspNetUserClaims i AspNetUserLogins są puste. Pole "rozróżniacz" w tabeli AspNetUser powinno być zgodne z nazwą klasy modelu, która jest zdefiniowana w następnym kroku. Ponadto kolumna PasswordHash ma postać "szyfrowanego hasła | sól hasła | format hasła". Pozwala to na użycie specjalnej logiki kryptograficznej członkostwa w programie SQL, aby można było ponownie używać starych haseł. Wyjaśniono w dalszej części artykułu.

Tworzenie modeli i stron członkostwa

Jak wspomniano wcześniej, funkcja Identity używa Entity Framework, aby komunikować się z bazą danych w celu zapisywanych domyślnie informacji o koncie. Aby można było korzystać z istniejących danych w tabeli, należy utworzyć klasy modeli, które mapują z powrotem do tabel i podłączają je do systemu tożsamości. W ramach kontraktu tożsamości klasy modelu powinny implementować interfejsy zdefiniowane w bibliotece DLL Identity. Core lub można zwiększyć istniejącą implementację tych interfejsów dostępnych w pliku Microsoft. AspNet. Identity. EntityFramework.

W naszym przykładzie tabele AspNetRoles, AspNetUserClaims, AspNetLogins i AspNetUserRole mają kolumny podobne do istniejącej implementacji systemu tożsamości. W związku z tym można ponownie użyć istniejących klas do mapowania na te tabele. Tabela AspNetUser zawiera dodatkowe kolumny, które są używane do przechowywania dodatkowych informacji z tabel członkostwa SQL. Można to zamapować przez utworzenie klasy modelu rozszerzającej istniejącą implementację elementu "IdentityUser" i dodanie dodatkowych właściwości.

  1. Utwórz folder models w projekcie i Dodaj użytkownika klasy. Nazwa klasy powinna być zgodna z danymi dodanymi w kolumnie "rozróżniacz" tabeli "AspnetUsers".

    Klasa User powinna mieć rozszerzoną klasę IdentityUser, która znajduje się w bibliotece DLL Microsoft. ASPNET. Identity. EntityFramework . Zadeklaruj właściwości w klasie, która mapuje z powrotem do kolumn AspNetUser. Właściwości ID, username, PasswordHash i SecurityStamp są zdefiniowane w IdentityUser i dlatego są pomijane. Poniżej znajduje się kod klasy użytkownika, która ma wszystkie właściwości

    public class User : IdentityUser
    {
        public User()
        {
            CreateDate = DateTime.Now;
            IsApproved = false;
            LastLoginDate = DateTime.Now;
            LastActivityDate = DateTime.Now;
            LastPasswordChangedDate = DateTime.Now;
            LastLockoutDate = DateTime.Parse("1/1/1754");
            FailedPasswordAnswerAttemptWindowStart = DateTime.Parse("1/1/1754");
            FailedPasswordAttemptWindowStart = DateTime.Parse("1/1/1754");
        }
    
        public System.Guid ApplicationId { get; set; }
        public string MobileAlias { get; set; }
        public bool IsAnonymous { get; set; }
        public System.DateTime LastActivityDate { get; set; }
        public string MobilePIN { get; set; }
        public string LoweredEmail { get; set; }
        public string LoweredUserName { get; set; }
        public string PasswordQuestion { get; set; }
        public string PasswordAnswer { get; set; }
        public bool IsApproved { get; set; }
        public bool IsLockedOut { get; set; }
        public System.DateTime CreateDate { get; set; }
        public System.DateTime LastLoginDate { get; set; }
        public System.DateTime LastPasswordChangedDate { get; set; }
        public System.DateTime LastLockoutDate { get; set; }
        public int FailedPasswordAttemptCount { get; set; }
        public System.DateTime FailedPasswordAttemptWindowStart { get; set; }
        public int FailedPasswordAnswerAttemptCount { get; set; }
        public System.DateTime FailedPasswordAnswerAttemptWindowStart { get; set; }
        public string Comment { get; set; }
    }
    
  2. Entity Framework DbContext Class jest wymagana w celu utrwalania danych w modelach z powrotem do tabel i pobierania danych z tabel w celu wypełnienia modeli. Plik Microsoft. ASPNET. Identity. EntityFramework DLL definiuje klasę IdentityDbContext, która współdziała z tabelami tożsamości w celu pobierania i przechowywania informacji. IdentityDbContext < Tuser > przyjmuje klasę "Tuser", która może być dowolną klasą, która rozszerza klasę IdentityUser.

    Utwórz nową klasę ApplicationDBContext, która rozszerza IdentityDbContext w folderze "models", przekazując w klasie "User" utworzonej w kroku 1

    public class ApplicationDbContext : IdentityDbContext<User>
    {
            
    }
    
  3. Zarządzanie użytkownikami w nowym systemie tożsamości odbywa się przy użyciu klasy Usermanager < Tuser > zdefiniowanej w bibliotece DLL Microsoft. ASPNET. Identity. EntityFramework . Musimy utworzyć klasę niestandardową, która rozszerza element Usermanager, przekazując w klasie "User" utworzonej w kroku 1.

    W folderze modele Utwórz nową klasę Usermanager, która rozszerza < użytkownika.>

    public class UserManager : UserManager<User>
    {
            
    }
    
  4. Hasła użytkowników aplikacji są szyfrowane i przechowywane w bazie danych programu. Algorytm kryptograficzny używany w członkostwie SQL jest inny niż w nowym systemie tożsamości. Aby ponownie użyć starych haseł, należy selektywnie odszyfrowywać hasła podczas logowania starych użytkowników przy użyciu algorytmu członkostwa SQL przy użyciu algorytmu kryptograficznego w tożsamości dla nowych użytkowników.

    Klasa Usermanager ma właściwość "PasswordHasher", która przechowuje wystąpienie klasy implementującej interfejs "IPasswordHasher". Służy do szyfrowania/odszyfrowywania haseł podczas transakcji uwierzytelniania użytkownika. W klasie Usermanager zdefiniowanej w kroku 3 Utwórz nową klasę SQLPasswordHasher i Skopiuj poniższy kod.

    public class SQLPasswordHasher : PasswordHasher
    {
        public override string HashPassword(string password)
        {
            return base.HashPassword(password);
        }
    
        public override PasswordVerificationResult VerifyHashedPassword(string  hashedPassword, string providedPassword)
        {
            string[] passwordProperties = hashedPassword.Split('|');
            if (passwordProperties.Length != 3)
            {
                return base.VerifyHashedPassword(hashedPassword, providedPassword);
            }
            else
            {
                string passwordHash = passwordProperties[0];
                int passwordformat = 1;
                string salt = passwordProperties[2];
                if (String.Equals(EncryptPassword(providedPassword, passwordformat, salt), passwordHash, StringComparison.CurrentCultureIgnoreCase))
                {
                    return PasswordVerificationResult.SuccessRehashNeeded;
                }
                else
                {
                    return PasswordVerificationResult.Failed;
                }
            }
        }
    
        //This is copied from the existing SQL providers and is provided only for back-compat.
        private string EncryptPassword(string pass, int passwordFormat, string salt)
        {
            if (passwordFormat == 0) // MembershipPasswordFormat.Clear
                return pass;
    
            byte[] bIn = Encoding.Unicode.GetBytes(pass);
            byte[] bSalt = Convert.FromBase64String(salt);
            byte[] bRet = null;
    
            if (passwordFormat == 1)
            { // MembershipPasswordFormat.Hashed 
                HashAlgorithm hm = HashAlgorithm.Create("SHA1");
                if (hm is KeyedHashAlgorithm)
                {
                    KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm;
                    if (kha.Key.Length == bSalt.Length)
                    {
                        kha.Key = bSalt;
                    }
                    else if (kha.Key.Length < bSalt.Length)
                    {
                        byte[] bKey = new byte[kha.Key.Length];
                        Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
                        kha.Key = bKey;
                    }
                    else
                    {
                        byte[] bKey = new byte[kha.Key.Length];
                        for (int iter = 0; iter < bKey.Length; )
                        {
                            int len = Math.Min(bSalt.Length, bKey.Length - iter);
                            Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
                            iter += len;
                        }
                        kha.Key = bKey;
                    }
                    bRet = kha.ComputeHash(bIn);
                }
                else
                {
                    byte[] bAll = new byte[bSalt.Length + bIn.Length];
                    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
                    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
                    bRet = hm.ComputeHash(bAll);
                }
            }
    
            return Convert.ToBase64String(bRet);
        }
    

    Usuń błędy kompilacji, importując przestrzenie nazw System. Text i system. Security. Cryptography.

    Metoda EncodePassword szyfruje hasło zgodnie z domyślną implementacją kryptograficzną członkostwa w programie SQL. Jest to pobierane z biblioteki DLL systemu system. Web. Jeśli stara aplikacja użyła niestandardowej implementacji, powinna zostać odzwierciedlona tutaj. Musimy zdefiniować dwie inne metody HashPassword i VerifyHashedPassword , które używają metody EncodePassword do mieszania danego hasła lub weryfikowania hasła w postaci zwykłego tekstu przy użyciu jednego z istniejących w bazie danych.

    System członkostwa SQL używa PasswordHash, PasswordSalt i PasswordFormat do mieszania hasła wprowadzonego przez użytkowników podczas rejestrowania lub zmiany hasła. Podczas migracji wszystkie trzy pola są przechowywane w kolumnie PasswordHash w tabeli AspNetUser oddzielonej znakiem "|". Gdy użytkownik loguje się, a hasło zawiera te pola, do sprawdzenia hasła używane są Kryptografia członkostwa SQL. w przeciwnym razie użyjemy domyślnego kryptografii systemu tożsamości do zweryfikowania hasła. W ten sposób stara użytkownicy nie będą musieli zmieniać haseł po migracji aplikacji.

  5. Zadeklaruj konstruktora dla klasy Usermanager i przekaż go jako SQLPasswordHasher do właściwości w konstruktorze.

    public UserManager()
                : base(new UserStore<User>(new ApplicationDbContext()))
    {
                this.PasswordHasher = new SQLPasswordHasher();
    }
    

Tworzenie nowych stron zarządzania kontami

Następny krok migracji polega na dodaniu stron zarządzania kontami, które pozwolą na rejestrację i zalogowanie użytkownika. Stare strony kont z członkostwa SQL używają kontroli, które nie współpracują z nowym systemem tożsamości. Aby dodać nowe strony zarządzania użytkownikami, postępuj zgodnie z samouczkiem z tego linku, https://www.asp.net/identity/overview/getting-started/adding-aspnet-identity-to-an-empty-or-existing-web-forms-project rozpoczynając od kroku "Dodawanie formularzy sieci Web do rejestracji użytkowników w aplikacji", ponieważ został już utworzony projekt i dodał pakiety NuGet.

Musimy wprowadzić pewne zmiany, aby przykład mógł współpracować z projektem.

  • W przypadku klas Register.aspx.cs i Login.aspx.cs związanych z klasami należy UserManager utworzyć użytkownika przy użyciu pakietów tożsamości. W tym przykładzie Użyj elementu Usermanager dodanego w folderze models, wykonując kroki wymienione wcześniej.

  • Użyj klasy utworzonej zamiast IdentityUser w kodzie Register.aspx.cs i Login.aspx.cs. Ten punkt zaczepienia w naszej niestandardowej klasie użytkownika do systemu tożsamości.

  • Część do utworzenia bazy danych może zostać pominięta.

  • Deweloper musi ustawić nowy użytkownik, aby pasował do bieżącego identyfikatora aplikacji. Można to zrobić, wykonując zapytania dotyczące tej aplikacji, zanim obiekt użytkownika zostanie utworzony w klasie Register.aspx.cs i ustawiając przed utworzeniem użytkownika.

    Przykład:

    Zdefiniuj metodę na stronie Register.aspx.cs, aby wysłać zapytanie do _ tabeli aplikacji ASPNET i uzyskać identyfikator aplikacji zgodnie z nazwą aplikacji

    private Guid GetApplicationID()
    {
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString))
        {
            string queryString = "SELECT ApplicationId from aspnet_Applications WHERE ApplicationName = '/'"; //Set application name as in database
    
            SqlCommand command = new SqlCommand(queryString, connection);
            command.Connection.Open();
    
            var reader = command.ExecuteReader();
            while (reader.Read())
            {
                return reader.GetGuid(0);
            }
    
            return Guid.NewGuid();
        }
    }
    

    Teraz ustaw tę wartość dla obiektu User

    var currentApplicationId = GetApplicationID();
    
    User user = new User() { UserName = Username.Text,
    ApplicationId=currentApplicationId, …};
    

Użyj starej nazwy użytkownika i hasła, aby zalogować istniejącego użytkownika. Na stronie Rejestracja Utwórz nowego użytkownika. Sprawdź również, czy użytkownicy znajdują się w rolach zgodnie z oczekiwaniami.

Przenoszenie do systemu tożsamości ułatwia użytkownikowi dodawanie uwierzytelniania Open Authentication (OAuth) do aplikacji. Zapoznaj się z przykładem z włączonym uwierzytelnianiem OAuth.

Następne kroki

W tym samouczku pokazano, jak przenieść użytkowników z członkostwa SQL do ASP.NET Identity, ale nie portem danych profilu. W następnym samouczku przejdziemy do przenoszenia danych profilu z członkostwa SQL do nowego systemu tożsamości.

Możesz opuścić opinię w dolnej części tego artykułu.

Dziękujemy za Dykstra i Rick Anderson w celu przejrzenia artykułu.