Partager via


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.

Membership Tables

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 :

  1. Sélectionnez Fichier>Nouveau>Projet.

  2. Créez un projet d’application web ASP.NET Core nommé CoreIdentitySample.

  3. 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.

  4. 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.

  5. Sélectionnez Outils>Gestionnaire de package NuGet>Console du Gestionnaire de package pour ouvrir la fenêtre Console du Gestionnaire de package (PMC).

  6. Accédez à la racine du projet dans PMC, puis exécutez la commande Entity Framework (EF) CoreUpdate-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-identity. Dans ce paramètre, EF Core est configuré pour utiliser la chaîne de connexion DefaultConnection.

    {
      "ConnectionStrings": {
        "DefaultConnection": "Server=localhost;Database=aspnet-core-identity;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }
    
  7. 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 de appsettings.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.

    Identity Tables

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 :

Fixed Login

É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.