Gyakorlat – Identitás testreszabása
Az előző leckében megtanulta, hogyan működik a testreszabás az ASP.NET Core Identityben. Ebben a leckében kiterjeszti az Identitás adatmodellt, és elvégezheti a megfelelő felhasználói felületi módosításokat.
A felhasználói fiók adatainak testreszabása
Ebben a szakaszban az alapértelmezett Razor-osztálytár helyett az Identitás felhasználói felületének fájljait fogja létrehozni és testre szabni.
Adja meg a projekt által módosítandó felhasználói regisztrációs fájlokat:
dotnet aspnet-codegenerator identity --dbContext RazorPagesPizzaAuth --files "Account.Manage.EnableAuthenticator;Account.Manage.Index;Account.Register;Account.ConfirmEmail" --userClass RazorPagesPizzaUser --force
A fenti parancsban:
- A
--dbContext
beállítás adja meg az eszköznek aDbContext
osztályból származtatottRazorPagesPizzaAuth
nevű osztály információit. - A
--files
beállítás azoknak az egyedi fájloknak a pontosvesszővel tagolt listáját adja meg, amelyeket fel kell venni az Identity területre. - A
--userClass
beállítás eredménye azIdentityUser
osztályból származtatottRazorPagesPizzaUser
nevű osztály létrehozása. - A
--force
beállítás hatására az Identitás területen meglévő fájlok felülíródnak.
Tipp
Futtassa a következő parancsot a projekt gyökeréből a beállítás érvényes értékeinek megtekintéséhez
--files
:dotnet aspnet-codegenerator identity --listFiles
Az alábbi fájlok lettek hozzáadva az Areas/Identity könyvtárhoz:
- Data/
- RazorPagesPizzaUser.cs
- Pages/
- _ViewImports.cshtml
- Account/
- _ViewImports.cshtml
- ConfirmEmail.cshtml
- ConfirmEmail.cshtml.cs
- Register.cshtml
- Register.cshtml.cs
- Manage/
- _ManageNav.cshtml
- _ViewImports.cshtml
- EnableAuthenticator.cshtml
- EnableAuthenticator.cshtml.cs
- Index.cshtml
- Index.cshtml.cs
- ManageNavPages.cs
Ugyanakkor a Data/RazorPagesPizzaAuth.cs fájl, amely már a parancs futtatása előtt is létezett, felül lett írva, mert a
--force
beállítást használtuk. ARazorPagesPizzaAuth
osztály deklarációja most az újonnan létrehozottRazorPagesPizzaUser
felhasználótípusra hivatkozik:public class RazorPagesPizzaAuth : IdentityDbContext<RazorPagesPizzaUser>
A EnableAuthenticator és ConfirmEmail a Razor-oldal állványzatú volt, de csak a modul későbbi részében módosultak.
- A
A-ben Program.csa hívásnak
AddDefaultIdentity
tisztában kell lennie az új identitásfelhasználói típussal. Foglalja bele az alábbi kiemelt módosításokat. (Az olvashatóság érdekében újraformált példa.)using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using RazorPagesPizza.Areas.Identity.Data; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection"); builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<RazorPagesPizzaUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<RazorPagesPizzaAuth>(); // Add services to the container. builder.Services.AddRazorPages();
Frissítsen Pages/Shared/_LoginPartial.cshtml az alábbi kiemelt módosítások felülre való beépítéséhez. Mentse a módosításokat.
@using Microsoft.AspNetCore.Identity @using RazorPagesPizza.Areas.Identity.Data @inject SignInManager<RazorPagesPizzaUser> SignInManager @inject UserManager<RazorPagesPizzaUser> UserManager <ul class="navbar-nav">
Az iménti módosítások megváltoztatják az
@inject
direktívákban aSignInManager<T>
és aUserManager<T>
számára átadott felhasználótípust. Az alapértelmezettIdentityUser
típus helyett márRazorPagesPizzaUser
típusú felhasználókra hivatkoznak. A@using
direktíva aRazorPagesPizzaUser
hivatkozások feloldásához lett felvéve.A Pages/Shared/_LoginPartial.cshtml fájl fizikailag az Identity területen kívül helyezkedik el. Az állványeszköz tehát nem frissítette automatikusan a fájlt. A megfelelő módosításokat manuálisan kell elvégezni.
Tipp
A _LoginPartial.cshtml fájlt annak manuális szerkesztése helyett törölheti is a generáló eszköz futtatása előtt. A _LoginPartial.cshtml fájl újra létrejön az új
RazorPagesPizzaUser
osztályra mutató hivatkozásokkal.Módosítsa az Areas/Identity/Data/RazorPagesPizzaUser.cs fájlt a további felhasználói profil-adatok tárolásának és lekérésének támogatásához. Hajtsa végre a következő módosításokat:
Vegye fel a
FirstName
és aLastName
tulajdonságot:public class RazorPagesPizzaUser : IdentityUser { [Required] [MaxLength(100)] public string FirstName { get; set; } = string.Empty; [Required] [MaxLength(100)] public string LastName { get; set; } = string.Empty; }
A fenti kódrészletben a tulajdonságok további oszlopoknak felelnek meg, amelyeket a mögöttes
AspNetUsers
táblában kell létrehozni. Mindkét tulajdonság megadása kötelező, ezért a[Required]
attribútummal vannak ellátva. Ezen felül a[MaxLength]
attribútum alapján legfeljebb 100 karakterből álló sztring engedélyezett. A mögöttes táblaoszlop adattípusa ennek megfelelően lesz definiálva. Az alapértelmezett érték vanstring.Empty
hozzárendelve, mivel a null értékű környezet engedélyezve van ebben a projektben, és a tulajdonságok nem null értékű sztringek.A fájl elején szúrja be az alábbi
using
utasítást.using System.ComponentModel.DataAnnotations;
A fenti kód a
FirstName
és aLastName
tulajdonságra alkalmazott adatjegyzet-attribútumokat oldja fel.
Az adatbázis frissítése
Most, hogy végrehajtotta a modell módosításait, a kapcsolódó módosításokat végre kell hajtani az adatbázison.
Győződjön meg arról, hogy az összes módosítás mentve van.
Hozzon létre és alkalmazzon egy EF Core-migrációt a mögöttes adattár frissítéséhez:
dotnet ef migrations add UpdateUser dotnet ef database update
Az
UpdateUser
EF Core-migráció egy DDL módosítási szkriptet alkalmazott azAspNetUsers
tábla sémájára. Pontosabban aFirstName
és aLastName
oszlopot adta hozzá, ahogyan a migráció kimenetének alábbi részletében látható:info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (37ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] ALTER TABLE [AspNetUsers] ADD [FirstName] nvarchar(100) NOT NULL DEFAULT N''; info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (36ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] ALTER TABLE [AspNetUsers] ADD [LastName] nvarchar(100) NOT NULL DEFAULT N'';
Vizsgálja meg az adatbázist az EF Core-migrálás
UpdateUser
táblasémáraAspNetUsers
gyakorolt hatásának elemzéséhez.A SQL Server panelen bontsa ki a dbo Oszlopok csomópontját. AspNetUsers tábla.
A
FirstName
osztály ésLastName
tulajdonságaiRazorPagesPizzaUser
azFirstName
előző képen szereplő ésLastName
oszlopnak felelnek meg. Anvarchar(100)
adattípus a[MaxLength(100)]
attribútumok miatt lett megadva a két oszlop mindegyikéhez. A nem null kényszer azért lett hozzáadva, mertFirstName
LastName
és az osztályban nem null értékű sztringek. A meglévő sorok üres sztringeket tartalmaznak az új oszlopokban.
A felhasználói regisztrációs űrlap testreszabása
Új oszlopokat adott hozzá a és LastName
a elemhezFirstName
. Most szerkesztenie kell a felhasználói felületet, hogy egyező mezőket jelenítsen meg a regisztrációs űrlapon.
Illessze be az alábbi kijelölt kódot az Areas/Identity/Pages/Account/Register.cshtml fájlba:
<form id="registerForm" asp-route-returnUrl="@Model.ReturnUrl" method="post"> <h2>Create a new account.</h2> <hr /> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-floating"> <input asp-for="Input.FirstName" class="form-control" /> <label asp-for="Input.FirstName"></label> <span asp-validation-for="Input.FirstName" class="text-danger"></span> </div> <div class="form-floating"> <input asp-for="Input.LastName" class="form-control" /> <label asp-for="Input.LastName"></label> <span asp-validation-for="Input.LastName" class="text-danger"></span> </div> <div class="form-floating"> <input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" /> <label asp-for="Input.Email"></label> <span asp-validation-for="Input.Email" class="text-danger"></span> </div>
A fenti kóddal az Utónév és a Vezetéknév szövegbeviteli mezőt vette fel a felhasználói regisztrációs űrlapra.
Az Areas/Identity/Pages/Account/Register.cshtml.cs fájlba vegye fel a név szövegbeviteli mezőinek támogatását.
A beágyazott
InputModel
osztályhoz adja meg aFirstName
és aLastName
tulajdonságot:public class InputModel { [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)] [Display(Name = "First name")] public string FirstName { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)] [Display(Name = "Last name")] public string LastName { get; set; } /// <summary> /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> [Required] [EmailAddress] [Display(Name = "Email")] public string Email { get; set; }
A
[Display]
attribútumok a szövegbeviteli mezőkkel társítandó címkék szövegét adják meg.Módosítsa az
OnPostAsync
metódust aRazorPagesPizza
objektumFirstName
ésLastName
tulajdonságának beállításához. Adja hozzá a következő kiemelt sorokat:public async Task<IActionResult> OnPostAsync(string returnUrl = null) { returnUrl ??= Url.Content("~/"); ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); if (ModelState.IsValid) { var user = CreateUser(); user.FirstName = Input.FirstName; user.LastName = Input.LastName; await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None); await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None); var result = await _userManager.CreateAsync(user, Input.Password);
A fenti módosítás a regisztrációs űrlapon bevitt felhasználói adatokra állítja be a
FirstName
és aLastName
tulajdonságot.
A webhely fejlécének testreszabása
Módosítsa úgy a Pages/Shared/_LoginPartial.cshtml fájlt, hogy megjelenítse a felhasználói regisztráció során bekért utónevet és vezetéknevet. Az alábbi kódrészlet kiemelt soraira lesz szükség:
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
RazorPagesPizzaUser user = await UserManager.GetUserAsync(User);
var fullName = $"{user.FirstName} {user.LastName}";
<li class="nav-item">
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello, @fullName!</a>
</li>
A profilkezelési űrlap testreszabása
Az új mezőket hozzáadta a felhasználói regisztrációs űrlaphoz, de a profilkezelési űrlaphoz is hozzá kell adnia őket, hogy a meglévő felhasználók szerkeszthesse őket.
Az Areas/Identity/Pages/Account/Manage/Index.cshtml fájlba illessze be az alábbi kódot. Mentse a módosításokat.
<form id="profile-form" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-floating"> <input asp-for="Input.FirstName" class="form-control" /> <label asp-for="Input.FirstName"></label> <span asp-validation-for="Input.FirstName" class="text-danger"></span> </div> <div class="form-floating"> <input asp-for="Input.LastName" class="form-control" /> <label asp-for="Input.LastName"></label> <span asp-validation-for="Input.LastName" class="text-danger"></span> </div> <div class="form-floating"> <input asp-for="Username" class="form-control" disabled /> <label asp-for="Username" class="form-label"></label> </div>
Végezze el az alábbi módosításokat az Areas/Identity/Pages/Account/Manage/Index.cshtml.cs fájlban a szövegbeviteli mezők támogatásához.
A beágyazott
InputModel
osztályhoz adja meg aFirstName
és aLastName
tulajdonságot:public class InputModel { [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)] [Display(Name = "First name")] public string FirstName { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)] [Display(Name = "Last name")] public string LastName { get; set; } [Phone] [Display(Name = "Phone number")] public string PhoneNumber { get; set; } }
Építse be a kiemelt módosításokat az
LoadAsync
metódusba:private async Task LoadAsync(RazorPagesPizzaUser user) { var userName = await _userManager.GetUserNameAsync(user); var phoneNumber = await _userManager.GetPhoneNumberAsync(user); Username = userName; Input = new InputModel { PhoneNumber = phoneNumber, FirstName = user.FirstName, LastName = user.LastName }; }
A fenti kód az utó- és vezetéknév lekérését támogatja a profilkezelési űrlap megfelelő mezőiben való megjelenítéshez.
Építse be a kiemelt módosításokat az
OnPostAsync
metódusba. Mentse a módosításokat.public async Task<IActionResult> OnPostAsync() { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } if (!ModelState.IsValid) { await LoadAsync(user); return Page(); } user.FirstName = Input.FirstName; user.LastName = Input.LastName; await _userManager.UpdateAsync(user); var phoneNumber = await _userManager.GetPhoneNumberAsync(user); if (Input.PhoneNumber != phoneNumber) { var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber); if (!setPhoneResult.Succeeded) { StatusMessage = "Unexpected error when trying to set phone number."; return RedirectToPage(); } } await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your profile has been updated"; return RedirectToPage(); }
A fenti kód az utó- és vezetéknévnek az adatbázis
AspNetUsers
táblájában végzett módosítását támogatja.
A megerősítő e-mail küldőjének konfigurálása
A megerősítő e-mail elküldéséhez létre kell hoznia egy implementációt IEmailSender , és regisztrálnia kell azt a függőséginjektálási rendszerben. Az egyszerűség érdekében az implementáció valójában nem küld e-mailt egy SMTP-kiszolgálónak. Csak az e-mail-tartalmat írja a konzolra.
Mivel az e-mailt egyszerű szövegben fogja megtekinteni a konzolon, a létrehozott üzenetet úgy kell módosítania, hogy kizárja a HTML-kódolású szöveget. A Areas/Identity/Pages/Account/Register.cshtml.cs területen keresse meg a következő kódot:
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
Módosítsa a következőre:
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by visiting the following URL:\r\n\r\n{callbackUrl}");
Az Explorer panelen kattintson a jobb gombbal a Szolgáltatások mappára, és hozzon létre egy új fájlt EmailSender.cs néven. Nyissa meg a fájlt, és adja hozzá a következő kódot:
using Microsoft.AspNetCore.Identity.UI.Services; namespace RazorPagesPizza.Services; public class EmailSender : IEmailSender { public EmailSender() {} public Task SendEmailAsync(string email, string subject, string htmlMessage) { Console.WriteLine(); Console.WriteLine("Email Confirmation Message"); Console.WriteLine("--------------------------"); Console.WriteLine($"TO: {email}"); Console.WriteLine($"SUBJECT: {subject}"); Console.WriteLine($"CONTENTS: {htmlMessage}"); Console.WriteLine(); return Task.CompletedTask; } }
Az előző kód létrehoz egy implementációt IEmailSender , amely az üzenet tartalmát írja a konzolra. Egy valós implementációban
SendEmailAsync
egy külső levelezőszolgáltatáshoz vagy más művelethez csatlakozna az e-mailek küldéséhez.A Program.cs fájlban adja hozzá a kiemelt sorokat:
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using RazorPagesPizza.Areas.Identity.Data; using Microsoft.AspNetCore.Identity.UI.Services; using RazorPagesPizza.Services; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection"); builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<RazorPagesPizzaUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<RazorPagesPizzaAuth>(); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddTransient<IEmailSender, EmailSender>(); var app = builder.Build();
Az előző a függőséginjektálási
EmailSender
IEmailSender
rendszerben regisztrálja magát.
A regisztrációs űrlap módosításainak tesztelése
Ez minden! Teszteljük a regisztrációs űrlap módosításait és a megerősítő e-mailt.
Győződjön meg arról, hogy az összes módosítást mentette.
A terminálpanelen hozza létre a projektet, és futtassa az alkalmazást a következővel:
dotnet run
.Nyissa meg az alkalmazást a böngészőben. Ha még be van jelentkezve, válassza a Kijelentkezés lehetőséget.
Válassza a Regisztráció lehetőséget, és regisztráljon új felhasználót a módosított űrlappal.
Megjegyzés
Az Utónév és a Vezetéknév mező érvényesítési megkötései az
InputModel
FirstName
ésLastName
tulajdonságának adatjegyzeteit tükrözik.A regisztrációt követően a rendszer átirányítja a Regisztráció megerősítő képernyőre. A terminálablakban görgessen felfelé a következőhöz hasonló konzolkimenet megkereséséhez:
Email Confirmation Message -------------------------- TO: jana.heinrich@contoso.com SUBJECT: Confirm your email CONTENTS: Please confirm your account by visiting the following URL: https://localhost:7192/Identity/Account/ConfirmEmail?<query string removed>
Navigáljon az URL-címre a Ctrl billentyűt lenyomva+tartva. Megjelenik a megerősítést kérő képernyő.
Megjegyzés
Ha GitHub Codespacest használ, előfordulhat, hogy hozzá kell adnia
-7192
a továbbított URL első részéhez. Például:scaling-potato-5gr4j4-7192.preview.app.github.dev
.Válassza a Bejelentkezés lehetőséget, és jelentkezzen be az új felhasználóval. Az alkalmazás fejlécében most a Hello, [Utónév] [Vezetéknév]! üzenet jelenik meg.
A VS Code SQL Server paneljén kattintson a jobb gombbal a RazorPagesPizza adatbázisra, és válassza az Új lekérdezés lehetőséget. A megjelenő lapon írja be a következő lekérdezést, és a CtrlShift+Ebillentyűkombinációt+ lenyomva futtassa.
SELECT UserName, Email, FirstName, LastName FROM dbo.AspNetUsers
Megjelenik a következőhöz hasonló eredményekkel rendelkező lap:
Felhasználónév E-mail FirstName LastName kai.klein@contoso.com kai.klein@contoso.com jana.heinrich@contoso.com jana.heinrich@contoso.com Jana Heinrich Az első felhasználó a
FirstName
és aLastName
sémához adása előtt regisztrált. A társítottAspNetUsers
táblarekordnak tehát nincsenek adatai ezekben az oszlopokban.
A profilkezelési űrlap módosításainak tesztelése
Tesztelje a profilkezelési űrlapon végrehajtott módosításokat is.
A webalkalmazásban jelentkezzen be az első létrehozott felhasználóval.
Válassza a Hello, ! hivatkozást a profilkezelési űrlapra való navigáláshoz.
Megjegyzés
A hivatkozás azért nem jelenik meg helyesen, mert az
AspNetUsers
táblának az ehhez a felhasználóhoz tartozó sora nem tartalmazza aFirstName
és aLastName
értéket.Adja meg az Utónév és a Vezetéknév érvényes értékét. Válassza a Mentés lehetőséget.
Az alkalmazás fejlécében a Hello, [Utónév] [Vezetéknév]! módosított üzenet jelenik meg.
Az alkalmazás leállításához nyomja le a CtrlCbillentyűkombinációt+ a VS Code terminálablakában.
Összefoglalás
Ebben a leckében testre szabta az identitást az egyéni felhasználói adatok tárolásához. A megerősítő e-mailt is testreszabta. A következő leckében megismerheti a többtényezős hitelesítés implementálását az Identityben.