Sdílet prostřednictvím


Migrace členských dat od univerzálního zprostředkovatele a uživatelských profilů na ASP.NET Identity (C#)

Pranav Rastogi, Rick Anderson, Robert McMurray, Suhas Joshi

Tento kurz popisuje kroky potřebné k migraci dat uživatelů a rolí a dat profilů uživatelů vytvořených pomocí univerzálních zprostředkovatelů existující aplikace do modelu ASP.NET Identity. Zde uvedený přístup k migraci dat profilů uživatelů je možné použít také v aplikaci s členstvím v SQL.

S vydáním Visual Studio 2013 tým ASP.NET představil nový systém identit ASP.NET a další informace o této verzi si můžete přečíst tady. V návaznosti na článek migrace webových aplikací z členství SQL do nového systému identit tento článek ukazuje postup migrace existujících aplikací, které se řídí modelem zprostředkovatelů pro správu uživatelů a rolí, do nového modelu identit. Tento kurz se zaměří především na migraci dat profilu uživatele, aby se bezproblémově zapusaly do nového systému. Migrace informací o uživateli a rolích je u členství SQL podobná. Postup migrace dat profilu je možné použít i v aplikaci s členstvím v SQL.

Jako příklad začneme webovou aplikací vytvořenou pomocí sady Visual Studio 2012, která používá model Providers. Pak přidáme kód pro správu profilů, zaregistrujeme uživatele, přidáme data profilu pro uživatele, migrujeme schéma databáze a pak změníme aplikaci tak, aby pro správu uživatelů a rolí používala systém identit. Jako test migrace by se uživatelé vytvořené pomocí univerzálních zprostředkovatelů měli mít možnost přihlásit a noví uživatelé by se měli mít možnost zaregistrovat.

Poznámka

Kompletní ukázku najdete na adrese https://github.com/suhasj/UniversalProviders-Identity-Migrations.

Souhrn migrace dat profilu

Než začneme s migracemi, podívejme se na prostředí ukládání dat profilu v modelu Providers. Data profilu pro uživatele aplikace mohou být uložena několika způsoby. Nejběžnější z nich je použití zabudovaných poskytovatelů profilů dodávaných společně s univerzálními poskytovateli. Kroky by zahrnovaly

  1. Přidejte třídu s vlastnostmi používanými k ukládání dat profilu.
  2. Přidejte třídu, která rozšiřuje profileBase a implementuje metody pro získání výše uvedených dat profilu pro uživatele.
  3. Povolte použití výchozích zprostředkovatelů profilu v souboruweb.config a definujte třídu deklarovanou v kroku 2 pro přístup k informacím o profilu.

Informace o profilu jsou uloženy jako serializovaná xml a binární data v tabulce Profilů v databázi.

Po migraci aplikace tak, aby používala nový systém identit ASP.NET, jsou informace profilu deserializovány a uloženy jako vlastnosti ve třídě uživatele. Každou vlastnost je pak možné namapovat na sloupce v tabulce uživatele. Výhodou je, že s vlastnostmi lze pracovat přímo pomocí třídy user kromě toho, že nemusíte serializovat nebo deserializovat informace o datech pokaždé při přístupu k ní.

začínáme

  1. Vytvořte novou aplikaci ASP.NET 4.5 Web Forms v sadě Visual Studio 2012. Aktuální ukázka používá šablonu Web Forms, ale můžete použít i aplikaci MVC.

    Snímek obrazovky s nově vytvořenou Web Forms aplikací v sadě Visual Studio 2012 pomocí šablony Web Forms

  2. Vytvoření nové složky Modely pro ukládání informací o profilu

    Snímek obrazovky s novou složkou s názvem Modely vytvořené pro ukládání informací o profilu

  3. Jako příklad můžeme uložit datum narození, město, výšku a váhu uživatele v profilu. Výška a váha se ukládají jako vlastní třída s názvem PersonalStats. K uložení a načtení profilu potřebujeme třídu, která rozšiřuje profileBase. Pojďme vytvořit novou třídu AppProfile, která bude získávat a ukládat informace o profilu.

    public class ProfileInfo
    {
        public ProfileInfo()
        {
            UserStats = new PersonalStats();
        }
        public DateTime? DateOfBirth { get; set; }
        public PersonalStats UserStats { get; set; }
        public string City { get; set; }
    }
    
    public class PersonalStats
    {
        public int? Weight { get; set; }
        public int? Height { get; set; }
    }
    
    public class AppProfile : ProfileBase
    {
        public ProfileInfo ProfileInfo
        {
            get { return (ProfileInfo)GetPropertyValue("ProfileInfo"); }
        }
        public static AppProfile GetProfile()
        {
            return (AppProfile)HttpContext.Current.Profile;
        }
        public static AppProfile GetProfile(string userName)
        {
            return (AppProfile)Create(userName);
        }
    }
    
  4. Povolte profil v souboruweb.config . Zadejte název třídy, který se má použít k ukládání nebo načítání informací o uživateli vytvořených v kroku 3.

    <profile defaultProvider="DefaultProfileProvider" enabled="true"
        inherits="UniversalProviders_ProfileMigrations.Models.AppProfile">
      <providers>
        .....
      </providers>
    </profile>
    
  5. Přidejte stránku webových formulářů do složky Účet, abyste získali data profilu od uživatele a uložili je. Klikněte pravým tlačítkem na projekt a vyberte Přidat novou položku. Přidejte novou stránku webových formuláře se stránkou předlohy AddProfileData.aspx. V části MainContent zkopírujte následující:

    <h2> Add Profile Data for <%# User.Identity.Name %></h2>
    <asp:Label Text="" ID="Result" runat="server" />
    <div>
        Date of Birth:
        <asp:TextBox runat="server" ID="DateOfBirth"/>
    </div>
    <div>
        Weight:
        <asp:TextBox runat="server" ID="Weight"/>
    </div>
    <div>
        Height:
        <asp:TextBox runat="server" ID="Height"/>
    </div>
    <div>
        City:
        <asp:TextBox runat="server" ID="City"/>
    </div>
    <div>
        <asp:Button Text="Add Profile" ID="Add" OnClick="Add_Click" runat="server" />
    </div>
    

    Do kódu na pozadí přidejte následující kód:

    protected void Add_Click(object sender, EventArgs e)
    {
        AppProfile profile = AppProfile.GetProfile(User.Identity.Name);
        profile.ProfileInfo.DateOfBirth = DateTime.Parse(DateOfBirth.Text);
        profile.ProfileInfo.UserStats.Weight = Int32.Parse(Weight.Text);
        profile.ProfileInfo.UserStats.Height = Int32.Parse(Height.Text);
        profile.ProfileInfo.City = City.Text;
        profile.Save();
    }
    

    Přidejte obor názvů, pod kterým je definovaná třída AppProfile, abyste odstranili chyby kompilace.

  6. Spusťte aplikaci a vytvořte nového uživatele s uživatelským jménem olduser. Přejděte na stránku AddProfileData a přidejte informace o profilu uživatele.

    Snímek obrazovky se stránkou Přidat data profilu pro přidání informací o profilu uživatele

Pomocí okna Průzkumník serveru můžete ověřit, že data jsou uložená jako serializovaná xml v tabulce Profily. V sadě Visual Studio v nabídce Zobrazit zvolte Průzkumník serveru. Pro databázi by mělo existovat datové připojení definované v souboruweb.config . Kliknutím na datové připojení se zobrazí různé podkategorie. Rozbalením tabulky zobrazte různé tabulky v databázi, klikněte pravým tlačítkem na Profily a zvolte Zobrazit data tabulky, abyste zobrazili data profilu uložená v tabulce Profily.

Snímek obrazovky s oknem Průzkumníka serveru, které zobrazuje data uložená v tabulce Profily

Snímek obrazovky s tabulkou dat Profilů

Migrace schématu databáze

Aby stávající databáze fungovala se systémem identit, musíme aktualizovat schéma v databázi identit tak, aby podporovalo pole přidaná do původní databáze. To lze provést pomocí skriptů SQL k vytvoření nových tabulek a zkopírování existujících informací. V okně Průzkumník serveru rozbalte položku DefaultConnection, aby se zobrazily tabulky. Klikněte pravým tlačítkem na Tabulky a vyberte Nový dotaz.

Snímek obrazovky s aktualizací schématu v databázi identit výběrem možnosti Nový dotaz

Vložte skript SQL z https://raw.github.com/suhasj/UniversalProviders-Identity-Migrations/master/Migration.txt a spusťte ho. Pokud se aktualizuje DefaultConnection, uvidíme, že se přidaly nové tabulky. Můžete zkontrolovat data uvnitř tabulek a zjistit, že informace byly migrovány.

Snímek obrazovky s aktualizací výchozího připojení a přidanými novými tabulkami

Migrace aplikace pro použití ASP.NET Identity

  1. Nainstalujte balíčky Nuget potřebné pro ASP.NET Identity:

    • Microsoft.AspNet.Identity.EntityFramework
    • Microsoft.AspNet.Identity.Owin
    • Microsoft.Owin.Host.SystemWeb
    • Microsoft.Owin.Security.Facebook
    • Microsoft.Owin.Security.Google
    • Microsoft.Owin.Security.MicrosoftAccount
    • Microsoft.Owin.Security.Twitter

    Další informace o správě balíčků NuGet najdete tady.

  2. Abychom mohli pracovat s existujícími daty v tabulce, musíme vytvořit třídy modelu, které se mapují zpět na tabulky, a propojit je v systému identit. Jako součást kontraktu identity by třídy modelu měly buď implementovat rozhraní definovaná v knihovně DLL Identity.Core, nebo mohou rozšířit stávající implementaci těchto rozhraní dostupných v Microsoft.AspNet.Identity.EntityFramework. Stávající třídy budeme používat pro role, přihlášení uživatelů a deklarace identity uživatelů. Pro naši ukázku musíme použít vlastního uživatele. Klikněte pravým tlačítkem na projekt a vytvořte novou složku IdentityModels. Přidejte novou třídu User, jak je znázorněno níže:

    using Microsoft.AspNet.Identity.EntityFramework;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using UniversalProviders_ProfileMigrations.Models;
    
    namespace UniversalProviders_Identity_Migrations
    {
        public class User : IdentityUser
        {
            public User()
            {
                CreateDate = DateTime.UtcNow;
                IsApproved = false;
                LastLoginDate = DateTime.UtcNow;
                LastActivityDate = DateTime.UtcNow;
                LastPasswordChangedDate = DateTime.UtcNow;
                Profile = new ProfileInfo();
            }
    
            public System.Guid ApplicationId { get; set; }
            public bool IsAnonymous { get; set; }
            public System.DateTime? LastActivityDate { get; set; }
            public string Email { 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; }
            public ProfileInfo Profile { get; set; }
        }
    }
    

    Všimněte si, že ProfileInfo je nyní vlastnost ve třídě uživatele. Proto můžeme použít třídu user k přímé práci s daty profilu.

Zkopírujte soubory ve složkách IdentityModels a IdentityAccount ze zdroje ke stažení ( https://github.com/suhasj/UniversalProviders-Identity-Migrations/tree/master/UniversalProviders-Identity-Migrations ). Mají zbývající třídy modelu a nové stránky potřebné pro správu uživatelů a rolí pomocí rozhraní API ASP.NET Identity. Použitý přístup se podobá členství SQL a podrobné vysvětlení najdete tady.

Některé příkazy nejsou podporované, pokud aplikace jako úložiště dat identity používá SQLite. Kvůli omezením v databázovém stroji Alter příkazy vyvolají následující výjimku:

System.NotSupportedException: SQLite nepodporuje tuto operaci migrace.

Pokud chcete změnit tabulky, spusťte v databázi migrace Code First.

Kopírování dat profilu do nových tabulek

Jak bylo zmíněno dříve, musíme deserializovat data XML v tabulkách Profiles a uložit je do sloupců tabulky AspNetUsers. Nové sloupce byly vytvořeny v tabulce users v předchozím kroku, takže zbývá jen naplnit tyto sloupce potřebnými daty. K tomu použijeme konzolovou aplikaci, která se jednou spustí k naplnění nově vytvořených sloupců v tabulce users.

  1. Ve ukončovacím řešení vytvořte novou konzolovou aplikaci.

    Snímek obrazovky s vytvořením nové konzolové aplikace v ukončovacím řešení

  2. Nainstalujte nejnovější verzi balíčku Entity Framework.

  3. Přidejte výše vytvořenou webovou aplikaci jako odkaz na konzolovou aplikaci. Uděláte to tak, že kliknete pravým tlačítkem na Project, pak na Přidat odkazy, pak na Řešení, kliknete na projekt a kliknete na OK.

  4. Zkopírujte následující kód ve třídě Program.cs. Tato logika čte data profilu pro každého uživatele, serializuje je jako objekt ProfileInfo a ukládá je zpět do databáze.

    public class Program
    {
        var dbContext = new ApplicationDbContext();
        foreach (var profile in dbContext.Profiles)
        {
            var stringId = profile.UserId.ToString();
            var user = dbContext.Users.Where(x => x.Id == stringId).FirstOrDefault();
            Console.WriteLine("Adding Profile for user:" + user.UserName);
            var serializer = new XmlSerializer(typeof(ProfileInfo));
            var stringReader = new StringReader(profile.PropertyValueStrings);
            var profileData = serializer.Deserialize(stringReader) as ProfileInfo;
            if (profileData == null)
            {
                Console.WriteLine("Profile data deserialization error for user:" + user.UserName);
            }
            else
            {
                user.Profile = profileData;
            }
        }
        dbContext.SaveChanges();
    }
    

    Některé z použitých modelů jsou definovány ve složce IdentityModels projektu webové aplikace, takže musíte zahrnout odpovídající obory názvů.

  5. Výše uvedený kód funguje se souborem databáze ve složce App_Data projektu webové aplikace vytvořeného v předchozích krocích. Pokud na to chcete odkazovat, aktualizujte připojovací řetězec v souboru app.config konzolové aplikace připojovacím řetězcem v web.config webové aplikace. Zadejte také úplnou fyzickou cestu ve vlastnosti AttachDbFilename.

  6. Otevřete příkazový řádek a přejděte do složky bin výše uvedené konzolové aplikace. Spusťte spustitelný soubor a zkontrolujte výstup protokolu, jak je znázorněno na následujícím obrázku.

    Snímek obrazovky se spustitelným souborem na příkazovém řádku pro spuštění a kontrolu výstupu protokolu

  7. Otevřete tabulku AspNetUsers v Průzkumníku serveru a ověřte data v nových sloupcích, které obsahují vlastnosti. Měly by se aktualizovat odpovídajícími hodnotami vlastností.

Ověření funkčnosti

K přihlášení uživatele ze staré databáze použijte nově přidané stránky členství, které jsou implementované pomocí ASP.NET Identity. Uživatel by měl být schopný se přihlásit pomocí stejných přihlašovacích údajů. Vyzkoušejte další funkce, jako je přidání OAuth, vytvoření nového uživatele, změna hesla, přidání rolí, přidání uživatelů do rolí atd.

Data profilu pro starého uživatele a nové uživatele by měla být načtena a uložena v tabulce uživatelů. Na starou tabulku by se už nemělo odkazovat.

Závěr

Tento článek popisuje proces migrace webových aplikací, které k ASP.NET Identity používaly model zprostředkovatele pro členství. Tento článek dále popisuje migraci dat profilu pro uživatele, kteří mají být připojeni k systému identit. Níže zanechte komentáře k dotazům a problémům, ke kterým dochází při migraci aplikace.

Díky Rick Anderson a Robert McMurray za přezkoumání článku.