Alıştırma - Identity’yi Özelleştirme

Tamamlandı

Önceki ünitede, özelleştirmenin ASP.NET Çekirdek Kimlik'te nasıl çalıştığını öğrendinsiniz. Bu ünitede Kimlik veri modelini genişletir ve ilgili kullanıcı arabirimi değişikliklerini yaparsınız.

Kullanıcı hesabı verilerini özelleştirme

Bu bölümde, kimlik kullanıcı arabirimi dosyalarını varsayılan Razor Sınıf Kitaplığı yerine kullanılacak şekilde oluşturacak ve özelleştireceksiniz.

  1. Değiştirilecek kullanıcı kaydı dosyalarını projeye ekleyin:

    dotnet aspnet-codegenerator identity --dbContext RazorPagesPizzaAuth --files "Account.Manage.EnableAuthenticator;Account.Manage.Index;Account.Register;Account.ConfirmEmail"
    

    Yukarıdaki komutta:

    • --dbContext seçeneği DbContext sınıfından türetilmiş RazorPagesPizzaAuth sınıfına yönelik bilgileri araca sağlar.
    • --files seçeneği Identity alanına eklenecek benzersiz dosyaların noktalı virgülle ayrılmış listesini belirtir.
      • Account.Manage.Index profil yönetimi sayfasıdır. Bu sayfa bu ünitenin ilerleyen bölümlerinde değiştirilmiştir.
      • Account.Register , kullanıcı kayıt sayfasıdır. Bu sayfa bu ünitede de değiştirilmiştir.
      • Account.Manage.EnableAuthenticator ve Account.ConfirmEmail yapı iskelesi yapılmıştır ancak bu ünitede değiştirilmez.

    İpucu

    Seçeneğin geçerli değerlerini görüntülemek için --files proje kökünden aşağıdaki komutu çalıştırın: dotnet aspnet-codegenerator identity --listFiles

    Aşağıdaki dosyalar Areas/Identity dizinine eklenir:

    • 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

Uzatmak IdentityUser

Kullanıcılarınızın adlarını depolamak için size yeni bir gereksinim verilir. Varsayılan IdentityUser sınıf ad ve soyad özellikleri içermediğinden sınıfını RazorPagesPizzaUser genişletmeniz gerekir.

dosyasında aşağıdaki değişiklikleri Areas/Identity/Data/RazorPagesPizzaUser.csyapın:

  1. FirstName ve LastName özelliklerini ekleyin:

    using System.ComponentModel.DataAnnotations;
    using Microsoft.AspNetCore.Identity;
    
    namespace RazorPagesPizza.Areas.Identity.Data;
    
    public class RazorPagesPizzaUser : IdentityUser
    {
        [Required]
        [MaxLength(100)]
        public string FirstName { get; set; } = string.Empty;
    
        [Required]
        [MaxLength(100)]
        public string LastName { get; set; } = string.Empty;
    }
    

    Yukarıdaki kod parçacığındaki özellikler, temel alınan AspNetUsers tablosunda oluşturulacak ek sütunları temsil eder. Her iki özellik de gerekli olduğundan, bunlara [Required] özniteliğiyle not eklenir. Ayrıca, [MaxLength] özniteliği maksimum uzunluk olarak 100 karaktere izin verildiğini belirtir. Temel alınan tablo sütununun veri türü de buna uygun olarak tanımlanır. Bu projede null atanabilir bağlam etkinleştirildiğinden ve özellikler null atanamaz dizeler olduğundan varsayılan değeri string.Empty atanır.

  2. Aşağıdaki using deyimini dosyanın en üstüne ekleyin.

    using System.ComponentModel.DataAnnotations;
    

    Yukarıdaki kod, FirstName ve LastName özelliklerine uygulanan veri açıklaması özniteliklerini çözümler.

Veritabanını güncelleştirme

Artık model değişiklikleri yapıldığına göre, veritabanında buna eşlik eden değişiklikler yapılmalıdır.

  1. Tüm değişikliklerinizin kaydedildiğinden emin olun.

  2. Temel alınan veri deposunu güncelleştirmek için EF Core geçişi oluşturma ve uygulama:

    dotnet ef migrations add UpdateUser
    dotnet ef database update
    

    UpdateUser EF Core geçişi, AspNetUsers tablosunun şemasına bir DDL değişiklik betiği uyguladı. Aşağıdaki geçiş çıkışı alıntısında görüldüğü gibi, özellikle FirstName ve LastName sütunları eklendi:

    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'';
    
  3. EF Core geçişinin UpdateUser tablonun şeması üzerindeki AspNetUsers etkisini analiz etmek için veritabanını inceleyin.

    SQL Server bölmesinde, dbo üzerindeki Sütunlar düğümünü genişletin. AspNetUsers tablosu.

    AspNetUsers tablosunun şemasının ekran görüntüsü.

    FirstName sınıfındaki RazorPagesPizzaUser ve LastName özellikleri, önceki görüntüdeki FirstName ve LastName sütunlarına karşılık gelir. [MaxLength(100)] öznitelikleri nedeniyle her iki sütuna da nvarchar(100) veri türü atandı. null olmayan kısıtlama eklendi çünkü FirstName ve LastName sınıfında null atanamaz dizeler. Mevcut satırlar, yeni sütunlarda boş dizeler gösterir.

Kullanıcı kaydı formunu özelleştirme

ve LastNameiçin FirstName yeni sütunlar eklediniz. Şimdi kayıt formunda eşleşen alanları görüntülemek için kullanıcı arabirimini düzenlemeniz gerekir.

  1. Areas/Identity/Pages/Account/Register.cshtml dosyasına aşağıda vurgulanmış işaretlemeyi ekleyin:

    <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" role="alert"></div>
        <div class="form-floating mb-3">
            <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 mb-3">
            <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 mb-3">
            <input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
            <label asp-for="Input.Email">Email</label>
            <span asp-validation-for="Input.Email" class="text-danger"></span>
        </div>
    

    Yukarıdaki işaretleme ile, Ad ve Soyadı metin kutuları kullanıcı kaydı formuna eklenir.

  2. Areas/Identity/Pages/Account/Register.cshtml.cs dosyasına ad metin kutuları için destek ekleyin.

    1. İç içe geçmiş InputModel sınıfına FirstName ve LastName özelliklerini ekleyin:

      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; }
      

      [Display] öznitelikleri, metin kutularıyla ilişkilendirilecek etiket metnini tanımlar.

    2. RazorPagesPizza nesnesinde FirstName ve LastName özelliklerini ayarlamak için OnPostAsync metodunu değiştirin. Aşağıdaki vurgulanmış satırları ekleyin:

      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);
      
      

      Yukarıdaki değişiklik, FirstName ve LastName özelliklerini kayıt formundaki kullanıcı girişine ayarlar.

Site üst bilgisini özelleştirme

Kullanıcı kaydı sırasında toplanan ad ve soyadı bilgilerini görüntülemek için Pages/Shared/_LoginPartial.cshtml dosyasını güncelleştirin. Aşağıdaki kod parçacığında vurgulanan satırlar gereklidir:

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

UserManager.GetUserAsync(User) null atanabilir RazorPagesPizzaUser bir nesne döndürür. null-koşullu ?. işleç, ve LastName özelliklerine yalnızca RazorPagesPizzaUser nesne null değilse erişmek FirstName için kullanılır.

Profil yönetimi formunu özelleştirme

Yeni alanları kullanıcı kayıt formuna eklediniz, ancak mevcut kullanıcıların düzenleyebilmesi için bunları profil yönetimi formuna da eklemeniz gerekir.

  1. Areas/Identity/Pages/Account/Manage/Index.cshtml dosyasına aşağıda vurgulanmış işaretlemeyi ekleyin. Değişikliklerinizi kaydedin.

    <form id="profile-form" method="post">
        <div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
        <div class="form-floating mb-3">
            <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 mb-3">
            <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 mb-3">
            <input asp-for="Username" class="form-control" disabled />
            <label asp-for="Username" class="form-label"></label>
        </div>
    
  2. Ad metin kutularına yönelik desteği sunmak için Areas/Identity/Pages/Account/Manage/Index.cshtml.cs dosyasında aşağıdaki değişiklikleri yapın.

    1. İç içe geçmiş InputModel sınıfına FirstName ve LastName özelliklerini ekleyin:

      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>
          [Phone]
          [Display(Name = "Phone number")]
          public string PhoneNumber { get; set; }
      }
      
    2. LoadAsync metodunda vurgulanan değişiklikleri ekleyin:

      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
          };
      }
      

      Yukarıdaki kod, profil yönetimi formunun karşılık gelen metin kutularında görüntülenmesi için ad ve soyadı bilgilerinin alınmasına yönelik destek sunar.

    3. Vurgulanan değişiklikleri OnPostAsync metoduna ekleyin. Değişikliklerinizi kaydedin.

      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();
      }
      

      Yukarıdaki kod, veritabanının AspNetUsers tablosunda yer alan ad ve soyadı bilgilerinin güncelleştirilmesine yönelik destek sunar.

Onay e-posta gönderenini yapılandırma

Uygulamayı ilk kez test edişiniz, bir kullanıcıyı kaydettiniz ve ardından kullanıcının e-posta adresini onaylama benzetimini yapmak için bir bağlantıya tıklamıştınız. Gerçek bir onay e-postası göndermek için uygulamasını oluşturup IEmailSender bağımlılık ekleme sistemine kaydetmeniz gerekir. İşleri basit tutmak için, bu ünitedeki uygulamanız aslında Basit Posta Aktarım Protokolü (SMTP) sunucusuna e-posta göndermez. Yalnızca e-posta içeriğini konsola yazar.

  1. E-postayı konsolda düz metin olarak görüntüleyeceksiniz çünkü oluşturulan iletiyi HTML ile kodlanmış metni dışlayacak şekilde değiştirmeniz gerekir. Alanlar/Kimlik/Sayfalar/Hesap/Register.cshtml.cs bölümünde aşağıdaki kodu bulun:

    await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
        $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
    

    Şu şekilde değiştirin:

    await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
        $"Please confirm your account by visiting the following URL:\r\n\r\n{callbackUrl}");
    
  2. Gezgin bölmesinde RazorPagesPizza\Services klasörüne sağ tıklayın ve EmailSender.cs adlı yeni bir dosya oluşturun. dosyasını açın ve aşağıdaki kodu ekleyin:

    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;
        }
    }
    

    Yukarıdaki kod, iletinin IEmailSender içeriğini konsola yazan bir uygulamasını oluşturur. Gerçek dünyadaki bir uygulamada, SendEmailAsync bir dış posta hizmetine veya e-posta göndermek için başka bir eyleme bağlanır.

  3. Program.cs vurgulanmış çizgileri ekleyin:

    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();
    

    Yukarıdaki, bağımlılık ekleme sisteminde olarak IEmailSender kaydederEmailSender.

Kayıt formundaki değişiklikleri test etme

Hepsi bu kadar! Şimdi kayıt formundaki değişiklikleri ve onay e-postasını test edelim.

  1. Tüm değişikliklerinizi kaydettiğinizden emin olun.

  2. Terminal bölmesinde projeyi derleyin ve uygulamasını ile dotnet runçalıştırın.

  3. Tarayıcınızda uygulamaya gidin. Oturum açtıysanız Oturumu kapat'ı seçin.

  4. Yeni bir kullanıcı kaydetmek için Kaydolun’u seçip güncelleştirilmiş formu kullanın.

    Not

    Ad ve Soyadı alanlarındaki doğrulama kısıtlamaları, InputModel sınıfını FirstName ve LastName özelliklerindeki veri açıklamalarını yansıtır.

  5. Kaydolduktan sonra Kayıt onay ekranına yönlendirilirsiniz. Terminal bölmesinde, aşağıdakine benzer konsol çıkışını bulmak için yukarı kaydırın:

    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>
    

    Ctrl tuşunu basılı tutarak URL'ye+gidin. Onay ekranı görüntülenir.

    Not

    GitHub Codespaces kullanıyorsanız, iletilen URL'nin ilk bölümüne eklemeniz -7192 gerekebilir. Örneğin, scaling-potato-5gr4j4-7192.preview.app.github.dev.

  6. Oturum aç'ı seçin ve yeni kullanıcıyla oturum açın. Uygulamanın üst bilgisi artık şunu içerir: Merhaba [Ad] [Soyadı]!.

  7. VS Code'daki SQL Server bölmesinde RazorPagesPizza veritabanına sağ tıklayın ve Yeni sorgu'yu seçin. Görüntülenen sekmeye aşağıdaki sorguyu girin ve çalıştırmak için Ctrl+Shift E tuşlarına+basın.

    SELECT UserName, Email, FirstName, LastName
    FROM dbo.AspNetUsers
    

    Aşağıdakine benzer sonuçlar içeren bir sekme görüntülenir:

    UserName E-posta FirstName LastName
    kai.klein@contoso.com kai.klein@contoso.com
    jana.heinrich@contoso.com jana.heinrich@contoso.com Jana Heinrich

    Şemaya ve LastName eklemeden FirstName önce kaydolan ilk kullanıcı. Bu nedenle ilişkili AspNetUsers tablo kaydında bu sütunlarda veri yoktur.

Profil yönetimi formundaki değişiklikleri test etme

Profil yönetimi formunda yaptığınız değişiklikleri de test etmelisiniz.

  1. Web uygulamasında, oluşturduğunuz ilk kullanıcıyla oturum açın.

  2. Profil yönetimi formuna gitmek için Merhaba! bağlantısını seçin.

    Not

    AspNetUsers tablosunun bu kullanıcıya yönelik satırı FirstName ve LastName değerlerini içermediğinden bağlantı düzgün şekilde görüntülenmez.

  3. Ad ve Soyadı için geçerli değerleri girin. Kaydet'i seçin.

    Uygulamanın üst bilgisi şöyle güncelleştirilir: Merhaba, [Ad] [Soyadı]!.

  4. Uygulamayı durdurmak için VS Code'daki terminal bölmesinde Ctrl+C tuşuna basın.

Özet

Bu ünitede, özel kullanıcı bilgilerini depolamak için Kimliği özelleştirmişsiniz. Onay e-postasını da özelleştirmişsiniz. Bir sonraki ünitede, Kimlik'te çok faktörlü kimlik doğrulamasını uygulama hakkında bilgi edineceksiniz.