Eseguire la migrazione dall'autenticazione di appartenenza ASP.NET a ASP.NET Core 2.0 Identity
Di Isaac Levin
Questo articolo illustra la migrazione dello schema del database per le app ASP.NET usando l'autenticazione di appartenenza a ASP.NET Core 2.0 Identity.
Nota
Questo documento illustra i passaggi necessari per eseguire la migrazione dello schema del database per ASP.NET app basate sull'appartenenza allo schema del database usato per ASP.NET Core Identity. Per altre informazioni sulla migrazione dall'autenticazione basata sull'appartenenza a ASP.NET a ASP.NET Identity, vedere Eseguire la migrazione di un'app esistente dall'appartenenza SQL a ASP.NET Identity. Per altre informazioni su ASP.NET Core Identity, vedere Introduzione a Identity in ASP.NET Core.
Revisione dello schema di appartenenza
Prima di ASP.NET 2.0, gli sviluppatori dovevano creare l'intero processo di autenticazione e autorizzazione per le app. Con ASP.NET 2.0, è stata introdotta l'appartenenza, fornendo una soluzione boilerplate per gestire la sicurezza all'interno delle app ASP.NET. Gli sviluppatori sono ora in grado di eseguire il bootstrap di uno schema in un database di SQL Server con lo strumento di registrazione di SQL Server ASP.NET () (Aspnet_regsql.exe
non più supportato). Dopo aver eseguito questo comando, nel database sono state create le tabelle seguenti.
Per eseguire la migrazione di app esistenti a ASP.NET Core 2.0 Identity, è necessario eseguire la migrazione dei dati in queste tabelle alle tabelle usate dal nuovo Identity schema.
schema ASP.NET Core Identity 2.0
ASP.NET Core 2.0 segue il Identity principio introdotto in ASP.NET 4.5. Anche se il principio è condiviso, l'implementazione tra i framework è diversa, anche tra le versioni di ASP.NET Core (vedere Eseguire la migrazione dell'autenticazione e Identity a ASP.NET Core 2.0).
Il modo più rapido per visualizzare lo schema per ASP.NET Core 2.0 Identity consiste nel creare una nuova app ASP.NET Core 2.0. Seguire questa procedura in Visual Studio 2017:
Selezionare File>New (Nuovo) >Project (Progetto).
Creare un nuovo progetto di applicazione Web core ASP.NET denominato CoreIdentitySample.
Selezionare ASP.NET Core 2.0 nell'elenco a discesa e quindi selezionare Applicazione Web. Questo modello produce un'app Razor Pages . Prima di fare clic su OK, fare clic su Modifica autenticazione.
Scegliere Account utente singoli per i Identity modelli. Infine, fare clic su OK, quindi su OK. Visual Studio crea un progetto usando il modello ASP.NET Core Identity .
Selezionare Strumenti>NuGet Gestione pacchetti> Gestione pacchetti Console per aprire la finestra Gestione pacchetti Console (PMC).
Passare alla radice del progetto in PMC ed eseguire il comando Entity Framework (EF) Core
Update-Database
.ASP.NET Core 2.0 Identity usa EF Core per interagire con il database che archivia i dati di autenticazione. Affinché l'app appena creata funzioni, è necessario che sia presente un database per archiviare questi dati. Dopo aver creato una nuova app, il modo più rapido per esaminare lo schema in un ambiente di database consiste nel creare il database usando EF Core Migrazioni. Questo processo crea un database, localmente o altrove, che simula tale schema. Per altre informazioni, vedere la documentazione precedente.
EF CoreI comandi usano il stringa di connessione per il database specificato in
appsettings.json
. Il stringa di connessione seguente è destinato a un database in localhost denominato asp-net-core-identity. In questa impostazione EF Core è configurato per l'uso delDefaultConnection
stringa di connessione.{ "ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=aspnet-core-identity;Trusted_Connection=True;MultipleActiveResultSets=true" } }
Avviso
Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.
Selezionare Visualizza>Esplora oggetti SQL Server. Espandere il nodo corrispondente al nome del database specificato nella
ConnectionStrings:DefaultConnection
proprietà diappsettings.json
.Il
Update-Database
comando ha creato il database specificato con lo schema ed eventuali dati necessari per l'inizializzazione dell'app. L'immagine seguente illustra la struttura della tabella creata con i passaggi precedenti.
Migrazione dello schema
Esistono piccole differenze nelle strutture di tabella e nei campi sia per Appartenenza che per ASP.NET Core Identity. Il modello è stato modificato in modo sostanziale per l'autenticazione/autorizzazione con le app ASP.NET e ASP.NET Core. Gli oggetti chiave ancora usati con Identity sono Utenti e Ruoli. Ecco le tabelle di mapping per Utenti, Ruoli e UserRoles.
Utenti
Identity ( dbo.AspNetUsers ) colonna |
Type | Appartenenze ( dbo.aspnet_Users / dbo.aspnet_Membership ) colonna |
Type |
---|---|---|---|
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
non esegue il mapping a LockoutEnabled
. IsLockedOut
è impostato se un utente ha avuto troppi accessi non riusciti ed è bloccato per un periodo di tempo impostato. LockoutEnabled
consente di bloccare un utente con troppi tentativi di accesso non riusciti. Quando l'utente ha troppi tentativi di accesso non riusciti, LockoutEnd
viene impostato su una data futura e l'utente non può accedere fino a tale data. Se LockoutEnabled
è false, un utente non viene mai bloccato per troppi tentativi di accesso non riusciti. Per OWASP, il blocco temporaneo dell'account dopo diversi tentativi non riusciti è troppo semplice di una destinazione per gli attacchi DoS contro gli utenti legittimi.
Per altre informazioni sul blocco, vedere Test OWASP per il meccanismo di blocco debole.
Le app che eseguono la migrazione a Identity che desiderano abilitare il blocco di accesso non riuscito devono essere impostate su LockoutEnabled
true come parte della migrazione.
Nota
Non tutti i mapping dei campi sono simili a relazioni uno-a-uno dall'appartenenza a ASP.NET Core Identity. La tabella precedente accetta lo schema user di appartenenza predefinito e lo esegue il mapping allo schema ASP.NET Core Identity . Tutti gli altri campi personalizzati usati per l'appartenenza devono essere mappati manualmente. In questo mapping non è disponibile alcuna mappa per le password, poiché i criteri di password e i salti delle password non eseguono la migrazione tra i due. È consigliabile lasciare la password null e chiedere agli utenti di reimpostare le password. In ASP.NET Core IdentityLockoutEnd
deve essere impostato su una data futura se l'utente è bloccato. Questo è illustrato nello script di migrazione.
Ruoli
Identity ( dbo.AspNetRoles ) colonna |
Type | Appartenenze ( dbo.aspnet_Roles ) colonna |
Type |
---|---|---|---|
Id |
string |
RoleId |
string |
Name |
string |
RoleName |
string |
NormalizedName |
string |
LoweredRoleName |
string |
User Roles
Identity ( dbo.AspNetUserRoles ) colonna |
Type | Appartenenze ( dbo.aspnet_UsersInRoles ) colonna |
Type |
---|---|---|---|
RoleId |
string |
RoleId |
string |
UserId |
string |
UserId |
string |
Fare riferimento alle tabelle di mapping precedenti durante la creazione di uno script di migrazione per utenti e ruoli. Nell'esempio seguente si presuppone che siano presenti due database in un server di database. Un database contiene lo schema e i dati di appartenenza ASP.NET esistenti. L'altro database CoreIdentitySample è stato creato usando i passaggi descritti in precedenza. I commenti sono inclusi inline per altri dettagli.
-- 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
Al termine dello script precedente, l'app ASP.NET Core Identity creata in precedenza viene popolata con Utenti di appartenenza. Gli utenti devono modificare le password prima di eseguire l'accesso.
Nota
Se il sistema di appartenenza aveva utenti con nomi utente che non corrispondono al proprio indirizzo di posta elettronica, le modifiche all'app create in precedenza sono necessarie per soddisfare questo problema. Il modello predefinito prevede UserName
e Email
deve essere lo stesso. Per le situazioni in cui sono diverse, il processo di accesso deve essere modificato in modo da usare UserName
invece di Email
.
Nell'oggetto PageModel
della pagina di accesso, che si trova in , rimuovere l'attributo [EmailAddress]
dalla proprietà Email . Rinominarlo in UserName. Ciò richiede una modifica ovunque EmailAddress
venga menzionata, nella visualizzazione e nel modello di pagina. Il risultato è simile al seguente:
Passaggi successivi
In questa esercitazione si è appreso come convertire gli utenti dall'appartenenza a SQL a ASP.NET Core 2.0 Identity. Per altre informazioni su ASP.NET Core Identity, vedere Introduzione a Identity.