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ı depolamanız için size yeni bir gereksinim verildi. 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. Add the `FirstName` and `LastName` properties:

    [!code-csharp[](../code/areas/identity/data/razorpagespizzauser.cs?highlight=3-5,7-9)]

    The properties in the preceding snippet represent additional columns to be created in the underlying `AspNetUsers` table. Both properties are required and are therefore annotated with the `[Required]` attribute. Additionally, the `[MaxLength]` attribute indicates that a maximum length of 100 characters is allowed. The underlying table column's data type is defined accordingly. A default value of `string.Empty` is assigned since nullable context is enabled in this project and the properties are non-nullable strings.

1. Add the following `using` statement to the top of the file.

    ```csharp
    using System.ComponentModel.DataAnnotations;
    ```

    The preceding code resolves the data annotation attributes applied to the `FirstName` and `LastName` properties.

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ç yalnızca nesne null değilse ve LastName özelliklerine RazorPagesPizzaUser 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 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. 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. 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

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