Migrer de l’authentification d’appartenance ASP.NET vers ASP.NET Core 2.0 Identity
De Isaac Levin
Cet article montre comment migrer le schéma de base de données des applications ASP.NET à l’aide de l’authentification d’appartenance vers ASP.NET Core 2.0 Identity.
Remarque
Ce document fournit les étapes à suivre pour migrer le schéma de base de données des applications basées sur l’appartenance ASP.NET vers le schéma de base de données utilisé pour ASP.NET Core Identity. Pour plus d’informations sur la migration de l’authentification basée sur l’appartenance ASP.NET vers ASP.NET Identity, consultez l’article Migration d’un site web existant de l’appartenance SQL vers ASP.NET Identity. Pour plus d’informations sur ASP.NET Core Identity, consultez l’article Présentation d’Identity sur ASP.NET Core.
Révision du schéma d’appartenance
Avant ASP.NET 2.0, les développeurs étaient chargés de créer l’ensemble du processus d’authentification et d’autorisation pour leurs applications. Avec ASP.NET 2.0, l’appartenance a été introduite pour fournir une solution réutilisable pour gérer la sécurité dans les applications ASP.NET. Les développeurs pouvaient alors amorcer un schéma dans une base de données SQL Server avec l’outil d’inscription ASP.NET SQL Server (Aspnet_regsql.exe
) (cet outil n’est plus pris en charge). Après l’exécution de cette commande, les tables suivantes étaient créées dans la base de données.
Pour migrer des applications existantes vers ASP.NET Core 2.0 Identity, les données de ces tables doivent être migrées vers les tables utilisées par le nouveau schéma Identity.
Schéma ASP.NET Core Identity 2.0
ASP.NET Core 2.0 suit le principe Identity introduit dans ASP.NET 4.5. Bien que ce principe soit partagé, l’implémentation entre les infrastructures est différente, même entre les versions de ASP.NET Core (consultez l’article Migrer l’authentification et Identity vers ASP.NET Core 2.0).
Le moyen le plus rapide d’afficher le schéma pour ASP.NET Core 2.0 Identity consiste à créer une application ASP.NET Core 2.0. Suivez la procédure ci-dessous dans Visual Studio 2017 :
Sélectionnez Fichier>Nouveau>Projet.
Créez un nouveau projet d’application web ASP.NET Core nommé CoreIdentitySample.
Sélectionnez ASP.NET Core 2.0 dans la liste déroulante, puis sélectionnez Application web. Ce modèle produit une application Razor Pages. Avant de cliquer sur OK, cliquez sur Modifier l’authentification.
Choisissez Comptes d’utilisateur individuels pour les modèles Identity. Enfin, cliquez sur OK, puis sur OK. Visual Studio crée un projet à l’aide du modèle ASP.NET CoreIdentity.
Sélectionnez Outils>Gestionnaire de package NuGet>Console du Gestionnaire de package pour ouvrir la fenêtre Console du Gestionnaire de package (PMC).
Accédez à la racine du projet dans PMC, puis exécutez la commande Entity Framework (EF) Core
Update-Database
.ASP.NET Core 2.0 Identity utilise EF Core pour interagir avec la base de données qui stocke les données d’authentification. Pour que la nouvelle application créée fonctionne, une base de données doit être présente pour stocker ces données. Après la création d’une application, le moyen le plus rapide d’inspecter le schéma dans un environnement de base de données consiste à créer la base de données à l’aide de migrations EF Core. Ce processus crée une base de données, localement ou ailleurs, qui imite ce schéma. Pour plus d’informations, consultez la documentation précédente.
Les commandes EF Core utilisent la chaîne de connexion pour la base de données spécifiée dans
appsettings.json
. La chaîne de connexion suivante cible une base de données sur localhost nommée asp-net-core-identityidentity. Dans ce paramètre, EF Core est configuré pour utiliser la chaîne de connexionDefaultConnection
.{ "ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=aspnet-core-identity;Trusted_Connection=True;MultipleActiveResultSets=true" } }
Avertissement
Cet article montre l’utilisation de chaîne de connexion s. Avec une base de données locale, l’utilisateur n’a pas besoin d’être authentifié, mais en production, les chaîne de connexion incluent parfois un mot de passe pour s’authentifier. Les informations d’identification de mot de passe du propriétaire de la ressource (ROPC) constituent un risque de sécurité qui doit être évité dans les bases de données de production. Les applications de production doivent utiliser le flux d’authentification le plus sécurisé disponible. Pour plus d’informations sur l’authentification des applications déployées pour tester ou produire des environnements, consultez Flux d’authentification sécurisés.
Sélectionnez Affichage>Explorateur d’objets SQL Server. Développez le nœud correspondant au nom de la base de données spécifié dans la propriété
ConnectionStrings:DefaultConnection
deappsettings.json
.La commande
Update-Database
a créé la base de données spécifiée avec le schéma et toutes les données nécessaires à l’initialisation de l’application. L’image suivante illustre la structure de table créée avec les étapes précédentes.
Migrer le schéma
Il existe des différences subtiles dans les structures et les champs de table pour l’appartenance et ASP.NET Core Identity. Le modèle a considérablement changé pour l’authentification/autorisation avec les applications ASP.NET et ASP.NET Core. Les objets clés qui sont toujours utilisés avec Identity sont Users et Roles. Voici des tables de mappage pour Users, Roles et UserRoles.
Utilisateurs
Identity Colonne ( dbo.AspNetUsers ) |
Type | Membership Colonne ( dbo.aspnet_Users / dbo.aspnet_Membership ) |
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
n’est pas mappé à LockoutEnabled
. IsLockedOut
est défini si un utilisateur a eu trop de connexions ayant échoué et est verrouillé pendant une période définie. LockoutEnabled
permet de verrouiller un utilisateur avec trop de tentatives de connexion ayant échoué. Quand l’utilisateur a trop de tentatives de connexion ayant échoué, LockoutEnd
est défini sur une date ultérieure et l’utilisateur ne peut pas se connecter avant cette date. Si LockoutEnabled
a la valeur false, un utilisateur n’est jamais verrouillé pour un trop grand nombre de tentatives de connexion ayant échoué. Selon OWASP, le verrouillage temporaire de compte après plusieurs tentatives ayant échoué est une cible trop simple pour les attaques DoS contre des utilisateurs légitimes.
Pour plus d’informations sur le verrouillage, consultez l’article OWASP Testing for Weak Lock Out Mechanism.
Pour les applications qui migrent vers Identity et qui souhaitent activer le verrouillage de connexion ayant échoué, LockoutEnabled
doit avoir la valeur true dans le cadre de la migration.
Remarque
Les mappages de champs ne ressemblent pas tous à des relations un-à-un de l’appartenance vers ASP.NET Core Identity. Le tableau précédent prend le schéma d’utilisateur d’appartenance par défaut et le mappe au schéma ASP.NET Core Identity. Tous les autres champs personnalisés utilisés pour l’appartenance doivent être mappés manuellement. Dans ce mappage, il n’y a pas de mappage pour les mots de passe, car les critères de mot de passe et les salts de mot de passe ne migrent pas entre les deux. Il est recommandé de laisser le mot de passe comme null et de demander aux utilisateurs de réinitialiser leur mot de passe. Dans ASP.NET Core Identity, LockoutEnd
doit être défini sur une date ultérieure si l’utilisateur est verrouillé. Cela s’affiche dans le script de migration.
Rôles
Identity Colonne ( dbo.AspNetRoles ) |
Type | Membership Colonne ( dbo.aspnet_Roles ) |
Type |
---|---|---|---|
Id |
string |
RoleId |
string |
Name |
string |
RoleName |
string |
NormalizedName |
string |
LoweredRoleName |
string |
Rôles d'utilisateur
Identity Colonne ( dbo.AspNetUserRoles ) |
Type | Membership Colonne ( dbo.aspnet_UsersInRoles ) |
Type |
---|---|---|---|
RoleId |
string |
RoleId |
string |
UserId |
string |
UserId |
string |
Référencez les tables de mappage précédentes lors de la création d’un script de migration pour Utilisateurs et Rôles. L’exemple suivant suppose que vous disposez de deux bases de données sur un serveur de base de données. Une base de données contient les données et le schéma d’appartenance ASP.NET existants. L’autre base de données CoreIdentitySample a été créée à l’aide d’une procédure décrite précédemment. Les commentaires sont inclus pour plus de détails.
-- 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
Une fois le script précédent terminé, l’application ASP.NET Core Identity créée précédemment est renseignée avec les utilisateurs d’appartenance. Les utilisateurs doivent modifier leur mot de passe avant de se connecter.
Remarque
Si le système d’appartenance avait des utilisateurs dont le nom d’utilisateur ne correspondait pas à leur adresse e-mail, des modifications doivent être apportées à l’application créée précédemment pour prendre en compte cette situation. Le modèle par défaut s’attend à ce que UserName
et Email
soient identiques. S’ils sont différents, le processus de connexion doit être modifié pour utiliser UserName
au lieu de Email
.
Dans la propriété PageModel
de la page de connexion, située dans , supprimez l’attribut [EmailAddress]
de la propriété Email. Renommez-la UserName. Cette modification doit être apportée partout où EmailAddress
est mentionné, dans View et PageModel. Le résultat se présente comme suit :
Étapes suivantes
Dans ce tutoriel, vous avez appris à migrer des utilisateurs de l’appartenance SQL vers ASP.NET Core 2.0 Identity. Pour plus d’informations sur ASP.NET Core Identity, consultez l’article Introduction à Identity.