Migration d’un site web existant de l’appartenance SQL vers ASP.NET Identity
par Rick Anderson, Suhas Joshi
Ce tutoriel illustre les étapes de migration d’une application web existante avec des données d’utilisateur et de rôle créées à l’aide de l’appartenance SQL vers le nouveau système ASP.NET Identity. Cette approche implique de remplacer le schéma de base de données existant par celui nécessaire par l’identité ASP.NET et de lui raccorder les anciennes/nouvelles classes. Une fois cette approche adoptée, une fois votre base de données migrée, les mises à jour futures vers Identity seront gérées sans effort.
Pour ce tutoriel, nous allons utiliser un modèle d’application web (Web Forms) créé à l’aide de Visual Studio 2010 pour créer des données d’utilisateur et de rôle. Nous allons ensuite utiliser des scripts SQL pour migrer la base de données existante vers les tables requises par le système d’identité. Ensuite, nous allons installer les packages NuGet nécessaires et ajouter de nouvelles pages de gestion de compte qui utilisent le système d’identité pour la gestion des appartenances. En tant que test de migration, les utilisateurs créés à l’aide de l’appartenance SQL doivent pouvoir se connecter et les nouveaux utilisateurs doivent pouvoir s’inscrire. Vous trouverez l’exemple complet ici. Consultez également Migration d’une appartenance ASP.NET vers ASP.NET Identity.
Prise en main
Création d’une application avec appartenance SQL
Nous devons commencer par une application existante qui utilise l’appartenance SQL et possède des données d’utilisateur et de rôle. Dans le cadre de cet article, nous allons créer une application web dans Visual Studio 2010.
À l’aide de l’outil de configuration ASP.NET, créez 2 utilisateurs : oldAdminUser et oldUser.
Créez un rôle nommé Administration et ajoutez « oldAdminUser » en tant qu’utilisateur dans ce rôle.
Créez une section Administration du site avec default.aspx. Définissez la balise d’autorisation dans le fichier web.config pour activer l’accès uniquement aux utilisateurs dans Administration rôles. Pour plus d’informations, cliquez ici. https://www.asp.net/web-forms/tutorials/security/roles/role-based-authorization-cs
Affichez la base de données dans Server Explorer pour comprendre les tables créées par le système d’appartenance SQL. Les données de connexion utilisateur sont stockées dans les tables aspnet_Users et aspnet_Membership, tandis que les données de rôle sont stockées dans la table aspnet_Roles. Informations sur les utilisateurs dans lesquels les rôles sont stockés dans la table aspnet_UsersInRoles. Pour la gestion des appartenances de base, il suffit de porter les informations des tables ci-dessus vers le système ASP.NET Identity.
Migration vers Visual Studio 2013
Installez Visual Studio Express 2013 pour web ou Visual Studio 2013 avec les dernières mises à jour.
Ouvrez le projet ci-dessus dans votre version installée de Visual Studio. Si SQL Server Express n’est pas installé sur l’ordinateur, une invite s’affiche lorsque vous ouvrez le projet, car la chaîne de connexion utilise SQL Express. Vous pouvez choisir d’installer SQL Express ou de modifier la chaîne de connexion en LocalDb. Pour cet article, nous allons le remplacer par LocalDb.
Ouvrez web.config et remplacez la chaîne de connexion par . SQLExpress vers (LocalDb)v11.0. Supprimez « User Instance=true » de la chaîne de connexion.
Ouvrez server Explorer et vérifiez que le schéma de table et les données peuvent être observés.
Le système d’identité ASP.NET fonctionne avec la version 4.5 ou ultérieure de l’infrastructure. Recibler l’application vers la version 4.5 ou ultérieure.
Générez le projet pour vérifier qu’il n’y a pas d’erreurs.
Installation des packages Nuget
Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet >Gérer les packages NuGet. Dans la zone de recherche, entrez « identité Asp.net ». Sélectionnez le package dans la liste des résultats, puis cliquez sur Installer. Acceptez le contrat de licence en cliquant sur le bouton « J’accepte ». Notez que ce package installe les packages de dépendances : EntityFramework et Microsoft ASP.NET Identity Core. De même, installez les packages suivants (ignorez les 4 derniers packages OWIN si vous ne souhaitez pas activer la connexion 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
Migrer la base de données vers le nouveau système d’identité
L’étape suivante consiste à migrer la base de données existante vers un schéma requis par le système ASP.NET Identity. Pour ce faire, nous exécutons un script SQL qui a un ensemble de commandes pour créer de nouvelles tables et migrer les informations utilisateur existantes vers les nouvelles tables. Le fichier de script est disponible ici.
Ce fichier de script est spécifique à cet exemple. Si le schéma des tables créées à l’aide de l’appartenance SQL est personnalisé ou modifié, les scripts doivent être modifiés en conséquence.
Comment générer le script SQL pour la migration de schéma
Pour que ASP.NET classes Identity fonctionnent prêtes à l’emploi avec les données des utilisateurs existants, nous devons migrer le schéma de base de données vers celui requis par ASP.NET Identity. Pour ce faire, nous pouvons ajouter de nouvelles tables et copier les informations existantes dans ces tables. Par défaut, ASP.NET Identity utilise EntityFramework pour mapper les classes de modèle d’identité à la base de données afin de stocker/récupérer des informations. Ces classes de modèle implémentent les interfaces d’identité principales qui définissent les objets utilisateur et rôle. Les tables et les colonnes de la base de données sont basées sur ces classes de modèle. Les classes de modèle EntityFramework dans Identity v2.1.0 et leurs propriétés sont telles que définies ci-dessous
IdentityUser | Type | IdentityRole | IdentityUserRole | IdentityUserLogin | IdentityUserClaim |
---|---|---|---|---|---|
Id | string | Id | RoleId | ProviderKey | Id |
Nom d’utilisateur | string | Nom | UserId | UserId | ClaimType |
PasswordHash | string | LoginProvider | ClaimValue | ||
SecurityStamp | string | User_id | |||
Courrier | string | ||||
EmailConfirmed | bool | ||||
PhoneNumber | string | ||||
PhoneNumberConfirmed | bool | ||||
LockoutEnabled | bool | ||||
LockoutEndDate | DateTime | ||||
AccessFailedCount | int |
Nous devons disposer de tables pour chacun de ces modèles avec des colonnes correspondant aux propriétés. Le mappage entre les classes et les tables est défini dans la OnModelCreating
méthode du IdentityDBContext
. Cette méthode est connue sous le nom de méthode de configuration de l’API Fluent et vous trouverez plus d’informations ici. La configuration des classes est celle indiquée ci-dessous.
Classe | Table | Clé primaire | Clé étrangère |
---|---|---|---|
IdentityUser | AspnetUsers | Id | |
IdentityRole | AspnetRoles | Id | |
IdentityUserRole | AspnetUserRole | UserId + RoleId | User_Id-AspnetUsers> RoleId-AspnetRoles> |
IdentityUserLogin | AspnetUserLogins | ProviderKey+UserId + LoginProvider | UserId-AspnetUsers> |
IdentityUserClaim | AspnetUserClaims | Id | User_Id-AspnetUsers> |
Avec ces informations, nous pouvons créer des instructions SQL pour créer de nouvelles tables. Nous pouvons écrire chaque instruction individuellement ou générer l’intégralité du script à l’aide de commandes EntityFramework PowerShell que nous pouvons ensuite modifier en fonction des besoins. Pour ce faire, dans VS, ouvrez la console du Gestionnaire de package à partir du menu Affichage ou Outils
- Exécutez la commande « Enable-Migrations » pour activer les migrations EntityFramework.
- Exécutez la commande « Add-migration initial » qui crée le code d’installation initial pour créer la base de données en C#/VB.
- La dernière étape consiste à exécuter la commande « Update-Database –Script » qui génère le script SQL en fonction des classes de modèle.
Certaines commandes ne sont pas prises en charge si l’application utilise SQLite comme magasin de données Identity. En raison des limitations du moteur de base de données,
Alter
les commandes lèvent l’exception suivante :« System.NotSupportedException : SQLite ne prend pas en charge cette opération de migration. »
Pour contourner le problème, exécutez les migrations Code First sur la base de données pour modifier les tables.
Ce script de génération de base de données peut être utilisé comme un début où nous allons apporter des modifications supplémentaires pour ajouter de nouvelles colonnes et copier des données. L’avantage est que nous générons la _MigrationHistory
table qui est utilisée par EntityFramework pour modifier le schéma de base de données lorsque les classes de modèle changent pour les versions ultérieures des versions d’Identity.
Les informations utilisateur d’appartenance SQL avaient d’autres propriétés en plus de celles de la classe de modèle utilisateur Identity, à savoir l’e-mail, les tentatives de mot de passe, la date de la dernière connexion, la date du dernier verrouillage, etc. Il s’agit d’informations utiles et nous aimerions qu’elles soient transmises au système d’identité. Pour ce faire, vous pouvez ajouter des propriétés supplémentaires au modèle utilisateur et les mapper aux colonnes de table de la base de données. Pour ce faire, ajoutez une classe qui sous-classe le IdentityUser
modèle. Nous pouvons ajouter les propriétés à cette classe personnalisée et modifier le script SQL pour ajouter les colonnes correspondantes lors de la création de la table. Le code de cette classe est décrit plus en détail dans l’article. Le script SQL pour la création de la AspnetUsers
table après l’ajout des nouvelles propriétés serait
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]),
);
Ensuite, nous devons copier les informations existantes de la base de données d’appartenance SQL vers les tables nouvellement ajoutées pour Identity. Cela peut être effectué via SQL en copiant des données directement d’une table vers une autre. Pour ajouter des données dans les lignes de la table, nous utilisons la INSERT INTO [Table]
construction. Pour copier à partir d’une autre table, nous pouvons utiliser l’instruction INSERT INTO
avec l’instruction SELECT
. Pour obtenir toutes les informations utilisateur, nous devons interroger les tables aspnet_Users et aspnet_Membership et copier les données dans la table AspNetUsers . Nous utilisons les INSERT INTO
instructions et SELECT
avec JOIN
et .LEFT OUTER JOIN
Pour plus d’informations sur l’interrogation et la copie de données entre des tables, reportez-vous à ce lien. En outre, les tables AspnetUserLogins et AspnetUserClaims sont vides pour commencer, car il n’existe aucune information dans l’appartenance SQL qui y correspond par défaut. Les seules informations copiées concernent les utilisateurs et les rôles. Pour le projet créé aux étapes précédentes, la requête SQL pour copier des informations dans la table users est
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;
Dans l’instruction SQL ci-dessus, les informations sur chaque utilisateur des tables aspnet_Users et aspnet_Membership sont copiées dans les colonnes de la table AspnetUsers . La seule modification effectuée ici consiste à copier le mot de passe. Étant donné que l’algorithme de chiffrement des mots de passe dans l’appartenance SQL a utilisé « PasswordSalt » et « PasswordFormat », nous les copieons également avec le mot de passe haché afin qu’il puisse être utilisé pour déchiffrer le mot de passe par Identity. Cela est expliqué plus en détail dans l’article lors du raccordement d’un hachage de mot de passe personnalisé.
Ce fichier de script est spécifique à cet exemple. Pour les applications qui ont des tables supplémentaires, les développeurs peuvent suivre une approche similaire pour ajouter des propriétés supplémentaires à la classe de modèle utilisateur et les mapper aux colonnes de la table AspnetUsers. Pour exécuter le script,
Ouvrez l’Explorateur de serveurs. Développez la connexion « ApplicationServices » pour afficher les tables. Cliquez avec le bouton droit sur le nœud Tables et sélectionnez l’option « Nouvelle requête »
Dans la fenêtre de requête, copiez et collez l’intégralité du script SQL à partir du fichier Migrations.sql. Exécutez le fichier de script en appuyant sur le bouton de direction « Exécuter ».
Actualisez la fenêtre Server Explorer. Cinq nouvelles tables sont créées dans la base de données.
Voici comment les informations contenues dans les tables d’appartenance SQL sont mappées au nouveau système d’identité.
aspnet_Roles --> AspNetRoles
asp_netUsers et asp_netMembership --> AspNetUsers
aspnet_UserInRoles --> AspNetUserRoles
Comme expliqué dans la section ci-dessus, les tables AspNetUserClaims et AspNetUserLogins sont vides. Le champ « Discriminator » dans la table AspNetUser doit correspondre au nom de la classe de modèle qui est défini comme étape suivante. En outre, la colonne PasswordHash se présente sous la forme « mot de passe chiffré |mot de passe salt|format de mot de passe ». Cela vous permet d’utiliser une logique de chiffrement d’appartenance SQL spéciale afin de pouvoir réutiliser les anciens mots de passe. Cela est expliqué plus loin dans l’article.
Création de modèles et de pages d’appartenance
Comme mentionné précédemment, la fonctionnalité Identité utilise Entity Framework pour communiquer avec la base de données afin de stocker les informations de compte par défaut. Pour utiliser des données existantes dans la table, nous devons créer des classes de modèle qui mappent aux tables et les raccorder dans le système d’identité. Dans le cadre du contrat Identity, les classes de modèle doivent soit implémenter les interfaces définies dans la dll Identity.Core, soit étendre l’implémentation existante de ces interfaces disponibles dans Microsoft.AspNet.Identity.EntityFramework.
Dans notre exemple, les tables AspNetRoles, AspNetUserClaims, AspNetLogins et AspNetUserRole ont des colonnes similaires à l’implémentation existante du système Identity. Par conséquent, nous pouvons réutiliser les classes existantes pour mapper à ces tables. La table AspNetUser contient des colonnes supplémentaires qui sont utilisées pour stocker des informations supplémentaires à partir des tables d’appartenance SQL. Cela peut être mappé en créant une classe de modèle qui étend l’implémentation existante de « IdentityUser » et ajoute les propriétés supplémentaires.
Créez un dossier Models dans le projet et ajoutez une classe User. Le nom de la classe doit correspondre aux données ajoutées dans la colonne « Discriminator » de la table « AspnetUsers ».
La classe User doit étendre la classe IdentityUser qui se trouve dans la dll Microsoft.AspNet.Identity.EntityFramework . Déclarez les propriétés de la classe qui sont mappées aux colonnes AspNetUser. Les propriétés ID, Username, PasswordHash et SecurityStamp sont définies dans IdentityUser et sont donc omises. Voici le code de la classe User qui a toutes les propriétés
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; } }
Une classe DbContext Entity Framework est nécessaire pour conserver les données des modèles dans les tables et récupérer les données des tables pour remplir les modèles. La dll Microsoft.AspNet.Identity.EntityFramework définit la classe IdentityDbContext qui interagit avec les tables Identity pour récupérer et stocker des informations. L’utilisateur tuser> IdentityDbContext<prend une classe « TUser », qui peut être n’importe quelle classe qui étend la classe IdentityUser.
Créez une classe ApplicationDBContext qui étend IdentityDbContext sous le dossier « Models », en passant la classe « User » créée à l’étape 1
public class ApplicationDbContext : IdentityDbContext<User> { }
La gestion des utilisateurs dans le nouveau système d’identité s’effectue à l’aide de la classe tuser> UserManager<définie dans la dll Microsoft.AspNet.Identity.EntityFramework. Nous devons créer une classe personnalisée qui étend UserManager, en passant la classe « User » créée à l’étape 1.
Dans le dossier Models, créez une classe UserManager qui étend l’utilisateur UserManager<>
public class UserManager : UserManager<User> { }
Les mots de passe des utilisateurs de l’application sont chiffrés et stockés dans la base de données. L’algorithme de chiffrement utilisé dans l’appartenance SQL est différent de celui du nouveau système d’identité. Pour réutiliser les anciens mots de passe, nous devons déchiffrer de manière sélective les mots de passe lorsque les anciens utilisateurs se connectent à l’aide de l’algorithme d’appartenances SQL tout en utilisant l’algorithme de chiffrement dans Identity pour les nouveaux utilisateurs.
La classe UserManager a une propriété « PasswordHasher » qui stocke un instance d’une classe qui implémente l’interface « IPasswordHasher ». Il est utilisé pour chiffrer/déchiffrer les mots de passe pendant les transactions d’authentification utilisateur. Dans la classe UserManager définie à l’étape 3, créez une classe SQLPasswordHasher et copiez le code ci-dessous.
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); }
Résolvez les erreurs de compilation en important les espaces de noms System.Text et System.Security.Cryptography.
La méthode EncodePassword chiffre le mot de passe en fonction de l’implémentation de chiffrement d’appartenance SQL par défaut. Elle est extraite de la dll System.Web. Si l’ancienne application utilisait une implémentation personnalisée, elle doit être reflétée ici. Nous devons définir deux autres méthodes HashPassword et VerifyHashedPassword qui utilisent la méthode EncodePassword pour hacher un mot de passe donné ou vérifier un mot de passe en texte brut avec celui existant dans la base de données.
Le système d’appartenance SQL a utilisé PasswordHash, PasswordSalt et PasswordFormat pour hacher le mot de passe entré par les utilisateurs lorsqu’ils s’inscrivent ou modifient leur mot de passe. Pendant la migration, les trois champs sont stockés dans la colonne PasswordHash de la table AspNetUser, séparés par le caractère « | ». Lorsqu’un utilisateur se connecte et que le mot de passe comporte ces champs, nous utilisons le chiffrement d’appartenance SQL pour case activée le mot de passe ; sinon, nous utilisons le chiffrement par défaut du système d’identité pour vérifier le mot de passe. De cette façon, les anciens utilisateurs n’auraient pas à modifier leurs mots de passe une fois l’application migrée.
Déclarez le constructeur pour la classe UserManager et transmettez-le en tant que SQLPasswordHasher à la propriété dans le constructeur.
public UserManager() : base(new UserStore<User>(new ApplicationDbContext())) { this.PasswordHasher = new SQLPasswordHasher(); }
Créer des pages de gestion de compte
L’étape suivante de la migration consiste à ajouter des pages de gestion de compte qui permettent à un utilisateur de s’inscrire et de se connecter. Les anciennes pages de compte de l’appartenance SQL utilisent des contrôles qui ne fonctionnent pas avec le nouveau système d’identité. Pour ajouter les nouvelles pages de gestion des utilisateurs, suivez le tutoriel sur ce lien https://www.asp.net/identity/overview/getting-started/adding-aspnet-identity-to-an-empty-or-existing-web-forms-project en commençant par l’étape « Ajout de Web Forms pour inscrire des utilisateurs dans votre application », car nous avons déjà créé le projet et ajouté les packages NuGet.
Nous devons apporter des modifications pour que l’exemple fonctionne avec le projet que nous avons ici.
Les classes Register.aspx.cs et Login.aspx.cs utilisent le
UserManager
à partir des packages d’identité pour créer un utilisateur. Pour cet exemple, utilisez le UserManager ajouté dans le dossier Models en suivant les étapes mentionnées précédemment.Utilisez la classe User créée au lieu des classes IdentityUser dans register.aspx.cs et login.aspx.cs code behind classes. Cette opération se connecte dans notre classe d’utilisateur personnalisée au système d’identité.
La partie permettant de créer la base de données peut être ignorée.
Le développeur doit définir l’Id d’application pour que le nouvel utilisateur corresponde à l’ID d’application actuel. Pour ce faire, interrogez l’Id d’application de cette application avant la création d’un objet utilisateur dans la classe Register.aspx.cs et définissez-le avant de créer un utilisateur.
Exemple :
Définir une méthode dans la page Register.aspx.cs pour interroger la table aspnet_Applications et obtenir l’ID d’application en fonction du nom de l’application
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(); } }
Maintenant, définissez-le sur l’objet utilisateur.
var currentApplicationId = GetApplicationID(); User user = new User() { UserName = Username.Text, ApplicationId=currentApplicationId, …};
Utilisez l’ancien nom d’utilisateur et le mot de passe pour connecter un utilisateur existant. Utilisez la page Inscrire pour créer un utilisateur. Vérifiez également que les utilisateurs ont des rôles comme prévu.
Le portage vers le système d’identité permet à l’utilisateur d’ajouter Open Authentication (OAuth) à l’application. Reportez-vous à l’exemple dans lequel OAuth est activé.
Étapes suivantes
Dans ce tutoriel, nous avons montré comment porter des utilisateurs de l’appartenance SQL vers ASP.NET Identity, mais nous n’avons pas porté de données de profil. Dans le tutoriel suivant, nous allons examiner le portage des données de profil de l’appartenance SQL vers le nouveau système d’identité.
Vous pouvez laisser des commentaires au bas de cet article.
Merci à Tom Dykstra et Rick Anderson d’avoir examiné l’article.