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

Tamamlandı

Önceki ünitede özelleştirmenin ASP.NET Core Identity'de 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" --userClass RazorPagesPizzaUser --force
    

    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.
    • --userClass seçeneği, IdentityUser sınıfından türetilmiş RazorPagesPizzaUser sınıfının oluşturulmasıyla sonuçlanır.
    • seçeneği, --forceKimlik alanındaki mevcut dosyaların üzerine yazılmasını sağlar.

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

    • 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

    Buna ek olarak, --force seçeneği kullanıldığından yukarıdaki komut çalıştırılmadan önce mevcut olan Data/RazorPagesPizzaAuth.cs dosyasının da üzerine yazılır. RazorPagesPizzaAuth sınıf bildirimi şimdi yeni oluşturulan RazorPagesPizzaUser kullanıcı türüne başvurur:

    public class RazorPagesPizzaAuth : IdentityDbContext<RazorPagesPizzaUser>
    

    EnableAuthenticator ve ConfirmEmail Razor sayfaları, modülün ilerleyen bölümlerine kadar değiştirilmese de iskelesi oluşturulmuştur.

  2. içinde Program.csçağrısının AddDefaultIdentity yeni Kimlik kullanıcı türüne dikkat edilmesi gerekir. Aşağıdaki vurgulanan değişiklikleri ekleyin. (Okunabilirlik için yeniden biçimlendirilen örnek.)

    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();
    
  3. Aşağıdaki vurgulanmış değişiklikleri en üste eklemek için güncelleştirin Pages/Shared/_LoginPartial.cshtml . Yaptığınız değişiklikleri kaydedin.

    @using Microsoft.AspNetCore.Identity
    @using RazorPagesPizza.Areas.Identity.Data
    @inject SignInManager<RazorPagesPizzaUser> SignInManager
    @inject UserManager<RazorPagesPizzaUser> UserManager
    
    <ul class="navbar-nav">
    

    Yukarıdaki değişiklikler, @inject yönergelerinde SignInManager<T> ve UserManager<T> öğelerine geçirilen kullanıcı türünü güncelleştirir. Varsayılan IdentityUser türünün yerine artık RazorPagesPizzaUser kullanıcısına başvurulur. RazorPagesPizzaUser başvurularını çözümlemek için @using yönergesi eklendi.

    Pages/Shared/_LoginPartial.cshtml, fiziksel olarak Identity alanının dışında bulunur. Bu nedenle, dosya iskele aracı tarafından otomatik olarak güncelleştirilmedi. Uygun değişiklikler el ile yapılmalıdır.

    İpucu

    _LoginPartial.cshtml dosyasını el ile düzenlemeye alternatif olarak dosya, iskele aracı çalıştırılmadan önce silinebilir. Dosya _LoginPartial.cshtml , yeni RazorPagesPizzaUser sınıfa başvurularla yeniden oluşturulur.

  4. Ek kullanıcı profili verilerinin alınmasını ve depolanmasını desteklemek için Areas/Identity/Data/RazorPagesPizzaUser.cs dosyasını güncelleştirin. Aşağıdaki değişiklikleri yapın:

    1. FirstName ve LastName özelliklerini ekleyin:

      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 boş değer atanamayan 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 boş değer atanamayan 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"></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>
    

    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>

Profil yönetimi formunu özelleştirme

Yeni alanları kullanıcı kayıt formuna eklediniz, ancak varolan 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. Yaptığınız değişiklikleri kaydedin.

    <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>
    
  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; }
      
          [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. Yaptığınız değişiklikleri 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-postası göndereni yapılandırma

Onay e-postasını göndermek için uygulamasını IEmailSender oluşturmanız ve bağımlılık ekleme sistemine kaydetmeniz gerekir. İşleri basit tutmak için uygulamanız aslında bir SMTP sunucusuna e-posta göndermez. Yalnızca e-posta içeriğini konsola yazar.

  1. Konsolda e-postayı düz metin olarak görüntüleyecek olduğunuzdan, oluşturulan iletiyi HTML ile kodlanmış metni dışlayacak şekilde değiştirmeniz gerekir. Alanlar/Kimlik/Sayfalar/Hesap/Register.cshtml.cs içinde 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 Hizmetler 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 bir uygulamada, SendEmailAsync bir dış posta hizmetine veya e-posta göndermek için başka bir eyleme bağlanır.

  3. Program.cs dosyasında vurgulanan satırları 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 bir IEmailSender olarak kaydedilirEmailSender.

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 ile dotnet runuygulamayı çalıştırın.

  3. Tarayıcınızda uygulamaya gidin. Oturumunuz hala açıksa Oturumu kapat seçeneğini belirleyin.

  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. Kayıt olduktan sonra Kayıt onayı ekranına yönlendirilirsiniz. Terminal bölmesinde yukarı kaydırarak aşağıdakine benzer konsol çıkışını bulun:

    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'un 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+ ShiftEtuşlarına+ basın.

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

    Aşağıdakine benzer sonuçlara sahip 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 dili Heinrich

    FirstName ve LastName öğelerini şemaya eklemeden ö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 Hello, ! 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ştirdiyseniz. Onay e-postasını da özelleştirdiyseniz. Bir sonraki ünitede Kimlik'te çok faktörlü kimlik doğrulamasını uygulamayı öğreneceksiniz.