Udostępnij za pośrednictwem


Migrowanie z uwierzytelniania członkostwa ASP.NET do ASP.NET Core 2.0 Identity

Autor: Isaac Levin

W tym artykule przedstawiono migrowanie schematu bazy danych dla aplikacji ASP.NET przy użyciu uwierzytelniania członkostwa do ASP.NET Core 2.0 Identity.

Uwaga

Ten dokument zawiera kroki niezbędne do przeprowadzenia migracji schematu bazy danych dla aplikacji opartych na członkostwie ASP.NET do schematu bazy danych używanego dla platformy ASP.NET Core Identity. Aby uzyskać więcej informacji na temat migracji z uwierzytelniania opartego na członkostwie ASP.NET do ASP.NET Identity, zobacz Migrowanie istniejącej aplikacji z członkostwa SQL do ASP.NET Identity. Aby uzyskać więcej informacji na temat ASP.NET Core Identity, zobacz Wprowadzenie do Identity ASP.NET Core.

Przegląd schematu członkostwa

Przed ASP.NET 2.0 deweloperzy mieli za zadanie utworzenie całego procesu uwierzytelniania i autoryzacji dla swoich aplikacji. Wraz z ASP.NET 2.0 wprowadzono członkostwo, zapewniając kociołowe rozwiązanie do obsługi zabezpieczeń w aplikacjach ASP.NET. Deweloperzy mogli teraz uruchomić schemat w bazie danych programu SQL Server przy użyciu narzędzia ASP.NET rejestracji programu SQL Server () (Aspnet_regsql.exenie jest już obsługiwane). Po uruchomieniu tego polecenia w bazie danych zostały utworzone następujące tabele.

Tabele członkostwa

Aby przeprowadzić migrację istniejących aplikacji do ASP.NET Core 2.0 Identity, dane w tych tabelach muszą zostać zmigrowane do tabel używanych przez nowy Identity schemat.

schemat ASP.NET Core Identity 2.0

ASP.NET Core 2.0 jest zgodna z zasadą wprowadzoną Identity w ASP.NET 4.5. Chociaż zasada jest współdzielona, implementacja między strukturami jest inna, nawet między wersjami ASP.NET Core (zobacz Migrowanie uwierzytelniania i Identity do ASP.NET Core 2.0).

Najszybszym sposobem wyświetlenia schematu dla platformy ASP.NET Core 2.0 Identity jest utworzenie nowej aplikacji ASP.NET Core 2.0. Wykonaj następujące kroki w programie Visual Studio 2017:

  1. Wybierz kolejno pozycje Plik>Nowy>Projekt.

  2. Utwórz nowy projekt aplikacji internetowej ASP.NET Core o nazwie CoreIdentitySample.

  3. Wybierz ASP.NET Core 2.0 na liście rozwijanej, a następnie wybierz pozycję Aplikacja internetowa. Ten szablon tworzy aplikację Razor Pages . Przed kliknięciem przycisku OK kliknij pozycję Zmień uwierzytelnianie.

  4. Wybierz pozycję Indywidualne konta użytkowników dla Identity szablonów. Na koniec kliknij przycisk OK, a następnie przycisk OK. Program Visual Studio tworzy projekt przy użyciu szablonu ASP.NET Core Identity .

  5. Wybierz pozycję Narzędzia Menedżer pakietów>NuGet> Menedżer pakietów Konsola, aby otworzyć okno konsoli Menedżer pakietów (PMC).

  6. Przejdź do katalogu głównego projektu w usłudze PMC i uruchom polecenie Entity Framework (EF) CoreUpdate-Database.

    ASP.NET Core 2.0 Identity używa EF Core do interakcji z bazą danych przechowującą dane uwierzytelniania. Aby nowo utworzona aplikacja działała, musi istnieć baza danych do przechowywania tych danych. Po utworzeniu nowej aplikacji najszybszym sposobem sprawdzenia schematu w środowisku bazy danych jest utworzenie bazy danych przy użyciu migracjiEF Core. Ten proces tworzy bazę danych lokalnie lub gdzie indziej, która naśladuje ten schemat. Aby uzyskać więcej informacji, zapoznaj się z poprzednią dokumentacją.

    EF CorePolecenia używają parametry połączenia dla bazy danych określonej w pliku appsettings.json. Następujące parametry połączenia dotyczą bazy danych na localhost o nazwie asp-net-core-identity. W tym ustawieniu EF Core skonfigurowano używanie DefaultConnection parametry połączenia.

    {
      "ConnectionStrings": {
        "DefaultConnection": "Server=localhost;Database=aspnet-core-identity;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }
    

Ostrzeżenie

W tym artykule przedstawiono użycie parametry połączenia. W przypadku lokalnej bazy danych użytkownik nie musi być uwierzytelniany, ale w środowisku produkcyjnym parametry połączenia czasami zawiera hasło do uwierzytelniania. Poświadczenie hasła właściciela zasobu (ROPC) jest zagrożeniem bezpieczeństwa, którego należy unikać w produkcyjnych bazach danych. Aplikacje produkcyjne powinny korzystać z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Aby uzyskać więcej informacji na temat uwierzytelniania aplikacji wdrożonych w środowiskach testowych lub produkcyjnych, zobacz Bezpieczne przepływy uwierzytelniania.

  1. Wybierz pozycję Wyświetl>Eksplorator obiektów programu SQL Server. Rozwiń węzeł odpowiadający nazwie bazy danych określonej we ConnectionStrings:DefaultConnection właściwości appsettings.json.

    Polecenie Update-Database utworzyło bazę danych określoną przy użyciu schematu i wszelkie dane potrzebne do inicjowania aplikacji. Na poniższej ilustracji przedstawiono strukturę tabeli utworzoną przy użyciu poprzednich kroków.

    Identity Tabel

Migrowanie schematu

Istnieją subtelne różnice w strukturach tabel i polach zarówno dla członkostwa, jak i ASP.NET Core Identity. Wzorzec zmienił się znacząco na potrzeby uwierzytelniania/autoryzacji przy użyciu aplikacji ASP.NET i ASP.NET Core. Kluczowe obiekty, które są nadal używane z usługą Identity , to Użytkownicy i role. Poniżej przedstawiono tabele mapowania użytkowników, ról i ról.

Użytkownicy

Identity
(dbo.AspNetUsers) kolumna
Typ Członkostwo
(dbo.aspnet_Users / dbo.aspnet_Membership) kolumna
Typ
Id string aspnet_Users.UserId string
UserName string aspnet_Users.UserName string
Email string aspnet_Membership.Email string
NormalizedUserName string aspnet_Users.LoweredUserName string
NormalizedEmail string aspnet_Membership.LoweredEmail string
PhoneNumber string aspnet_Users.MobileAlias string
LockoutEnabled bit aspnet_Membership.IsLockedOut bit

IsLockedOut nie mapuje na LockoutEnabled. IsLockedOut jest ustawiona, jeśli użytkownik miał zbyt wiele nieudanych logowań i jest zablokowany przez ustawiony czas. LockoutEnabled Umożliwia zablokowanie użytkownika z zbyt wieloma nieudanymi próbami logowania. Gdy użytkownik ma zbyt wiele nieudanych prób logowania, LockoutEnd jest ustawiony na datę w przyszłości, a użytkownik nie może się zalogować do tej daty. Jeśli LockoutEnabled jest to fałsz, użytkownik nigdy nie jest zablokowany dla zbyt wielu nieudanych prób logowania. Na OWASP, tymczasowe blokowanie konta po kilku nieudanych próbach jest zbyt proste w przypadku ataków DoS na uzasadnionych użytkowników.

Aby uzyskać więcej informacji na temat blokowania, zobacz Testowanie OWASP dla mechanizmu słabej blokady.

Aplikacje migrujące do Identity tej opcji, które chcą włączyć blokadę logowania, której nie można uruchomić, powinny mieć wartość LockoutEnabled true w ramach migracji.

Uwaga

Nie wszystkie mapowania pól przypominają relacje jeden do jednego z członkostwa do ASP.NET Core Identity. Poprzednia tabela przyjmuje domyślny schemat Użytkownika członkostwa i mapuje go na schemat ASP.NET Core Identity . Wszystkie inne pola niestandardowe, które były używane do członkostwa, muszą być mapowane ręcznie. W tym mapowaniu nie ma mapy haseł, ponieważ zarówno kryteria hasła, jak i sole haseł nie są migrowane między nimi. Zaleca się pozostawienie hasła jako wartości null i monitowanie użytkowników o zresetowanie swoich haseł. W ASP.NET Core IdentityLockoutEnd należy ustawić datę w przyszłości, jeśli użytkownik jest zablokowany. Jest to wyświetlane w skrygcie migracji.

Role

Identity
(dbo.AspNetRoles) kolumna
Typ Członkostwo
(dbo.aspnet_Roles) kolumna
Typ
Id string RoleId string
Name string RoleName string
NormalizedName string LoweredRoleName string

Role użytkowników

Identity
(dbo.AspNetUserRoles) kolumna
Typ Członkostwo
(dbo.aspnet_UsersInRoles) kolumna
Typ
RoleId string RoleId string
UserId string UserId string

Odwołaj się do powyższych tabel mapowania podczas tworzenia skryptu migracji dla użytkowników i ról. W poniższym przykładzie założono, że masz dwie bazy danych na serwerze bazy danych. Jedna baza danych zawiera istniejący schemat członkostwa i dane ASP.NET. Druga baza danych CoreIdentitySample została utworzona przy użyciu opisanych wcześniej kroków. Komentarze są dołączane w tekście, aby uzyskać więcej szczegółów.

-- THIS SCRIPT NEEDS TO RUN FROM THE CONTEXT OF THE MEMBERSHIP DB
BEGIN TRANSACTION MigrateUsersAndRoles
USE aspnetdb

-- INSERT USERS
INSERT INTO CoreIdentitySample.dbo.AspNetUsers
            (Id,
             UserName,
             NormalizedUserName,
             PasswordHash,
             SecurityStamp,
             EmailConfirmed,
             PhoneNumber,
             PhoneNumberConfirmed,
             TwoFactorEnabled,
             LockoutEnd,
             LockoutEnabled,
             AccessFailedCount,
             Email,
             NormalizedEmail)
SELECT aspnet_Users.UserId,
       aspnet_Users.UserName,
       -- The NormalizedUserName value is upper case in ASP.NET Core Identity
       UPPER(aspnet_Users.UserName),
       -- Creates an empty password since passwords don't map between the 2 schemas
       '',
       /*
        The SecurityStamp token is used to verify the state of an account and
        is subject to change at any time. It should be initialized as a new ID.
       */
       NewID(),
       /*
        EmailConfirmed is set when a new user is created and confirmed via email.
        Users must have this set during migration to reset passwords.
       */
       1,
       aspnet_Users.MobileAlias,
       CASE
         WHEN aspnet_Users.MobileAlias IS NULL THEN 0
         ELSE 1
       END,
       -- 2FA likely wasn't setup in Membership for users, so setting as false.
       0,
       CASE
         -- Setting lockout date to time in the future (1,000 years)
         WHEN aspnet_Membership.IsLockedOut = 1 THEN Dateadd(year, 1000,
                                                     Sysutcdatetime())
         ELSE NULL
       END,
       aspnet_Membership.IsLockedOut,
       /*
        AccessFailedAccount is used to track failed logins. This is stored in
        Membership in multiple columns. Setting to 0 arbitrarily.
       */
       0,
       aspnet_Membership.Email,
       -- The NormalizedEmail value is upper case in ASP.NET Core Identity
       UPPER(aspnet_Membership.Email)
FROM   aspnet_Users
       LEFT OUTER JOIN aspnet_Membership
                    ON aspnet_Membership.ApplicationId =
                       aspnet_Users.ApplicationId
                       AND aspnet_Users.UserId = aspnet_Membership.UserId
       LEFT OUTER JOIN CoreIdentitySample.dbo.AspNetUsers
                    ON aspnet_Membership.UserId = AspNetUsers.Id
WHERE  AspNetUsers.Id IS NULL

-- INSERT ROLES
INSERT INTO CoreIdentitySample.dbo.AspNetRoles(Id, Name)
SELECT RoleId, RoleName
FROM aspnet_Roles;

-- INSERT USER ROLES
INSERT INTO CoreIdentitySample.dbo.AspNetUserRoles(UserId, RoleId)
SELECT UserId, RoleId
FROM aspnet_UsersInRoles;

IF @@ERROR <> 0
  BEGIN
    ROLLBACK TRANSACTION MigrateUsersAndRoles
    RETURN
  END

COMMIT TRANSACTION MigrateUsersAndRoles

Po zakończeniu poprzedniego skryptu utworzona wcześniej aplikacja ASP.NET Core Identity zostanie wypełniona użytkownikami członkostwa. Użytkownicy muszą zmienić swoje hasła przed zalogowaniem się.

Uwaga

Jeśli system członkostwa miał użytkowników z nazwami użytkowników, którzy nie są zgodni z ich adresem e-mail, zmiany są wymagane do aplikacji utworzonej wcześniej, aby ją uwzględnić. Domyślny szablon oczekuje UserName i Email będzie taki sam. W sytuacjach, w których są różne, proces logowania należy zmodyfikować, aby zamiast UserNameEmail.

PageModel Na stronie logowania znajdującej się w lokalizacji usuń [EmailAddress] atrybut z właściwości Email. Zmień jego nazwę na UserName. Wymaga to zmiany wszędzie tam, gdzie EmailAddress jest wymieniona, w widoku i modelu PageModel. Wynik wygląda następująco:

Naprawiono logowanie

Następne kroki

W tym samouczku przedstawiono sposób przenoszenia użytkowników z członkostwa SQL do ASP.NET Core 2.0 Identity. Aby uzyskać więcej informacji na temat ASP.NET Core Identity, zobacz Wprowadzenie do Identityprogramu .